首页
/ FastAPI 高级中间件(Advanced Middleware)完全指南:集成任意 ASGI 中间件与内置中间件实战

FastAPI 高级中间件(Advanced Middleware)完全指南:集成任意 ASGI 中间件与内置中间件实战

2026-09-06 19:18:27作者:贡沫苏Truman

本篇技术指南以 FastAPI 高级用户指南中的 Middleware Avanzado(高级中间件)章节英文原版)为核心,系统讲解 FastAPI 项目中中间件的进阶用法:如何把任意符合 ASGI 规范的第三方中间件接入应用,以及仓库内置/内置集成的 HTTPSRedirectMiddlewareTrustedHostMiddlewareGZipMiddleware 等中间件的正确配置方式与参数语义。读完本文,你将掌握 app.add_middleware() 的接入机制、各内置中间件的安全与性能价值,并能在自己的 FastAPI 应用中独立完成 HTTPS 强制跳转、Host 校验和 GZip 压缩等生产级配置。

在正文开始之前,建议先回顾两篇前置章节:自定义中间件的创建方式见 Middleware 教程章节,跨域场景的 CORSMiddleware 用法见 CORS 章节。本文讨论的是这两者之外的“其他中间件”用法。

FastAPI 为什么可以接入任意 ASGI 中间件

FastAPI 是基于 Starlette 构建的,而 Starlette 完整实现了 ASGI 规范(异步服务器网关接口)。这意味着:

  • 只要一个组件遵循 ASGI 规范,它就不需要专门为 FastAPI 或 Starlette 定制,也能无缝接入应用;
  • 一般而言,ASGI 中间件就是一类“期望把某个 ASGI 应用作为第一个构造参数接收”的类,通过“包裹”下一层应用实现对请求/响应的拦截与加工。

在第三方 ASGI 中间件的文档中,你常见到的是类似下面的用法——直接手工构建新的应用对象:

from unicorn import UnicornMiddleware

app = SomeASGIApp()

new_app = UnicornMiddleware(app, some_config="rainbow")

app.add_middleware() 接入第三方 ASGI 中间件

直接手工包裹的问题是:这样生成的 new_app 脱离了 FastAPI 内部的中件夹栈管理,无法保证服务端错误处理ServerErrorMiddleware)与自定义异常处理器ExceptionMiddleware)正常工作。因此 FastAPI(更准确说是 Starlette)提供了更简单也更稳妥的方式——app.add_middleware()

from fastapi import FastAPI
from unicorn import UnicornMiddleware

app = FastAPI()

app.add_middleware(UnicornMiddleware, some_config="rainbow")

app.add_middleware() 第一个参数接收中间件类,其后紧跟任意需要传递给该中间件的附加参数(构造参数),如这里的 some_config="rainbow"

从源码看 add_middleware 的中间件栈机制

为什么用 add_middleware 就能保证异常处理正常?可以从仓库的 FastAPI 实现找到依据:

  • FastAPI 类本身继承自 Starlette(见 fastapi/applications.py),因此 add_middleware() 方法来自 Starlette 基类;
  • FastAPI 在 __init__ 中维护 self.user_middleware 列表(fastapi/applications.py),每次调用 add_middleware() 就是把中间件类追加进该列表,随后触发 setup() 重建中间件栈;
  • FastAPI 重写了 setup()fastapi/applications.py)与 build_middleware_stack()fastapi/applications.py),其核心组装逻辑是:
[ServerErrorMiddleware] + self.user_middleware + [ExceptionMiddleware, AsyncExitStackMiddleware]

也就是说,你通过 add_middleware() 注册的中间件会落在 ServerErrorMiddleware 内部、ExceptionMiddleware 外部。这样 500 级服务器错误仍会被最外层兜底处理,路由抛出的异常也仍会经过你注册的中间件链最终交给自定义异常处理器——这正是文档强调“内部中间件处理服务器错误、自定义异常处理器正常工作”的源码级原因。FastAPI 在构建栈时额外加入了 AsyncExitStackMiddleware(位于最内层),用于关闭依赖与上传文件等资源。

关于顺序:后添加的中间件更“靠外”

如果在构造阶段传入 middleware 参数,或在运行期多次调用 add_middleware(),每个新中间件都会包裹已存在的应用形成栈。请求进入时最外层先执行,响应返回时最后执行;FastAPI 会把栈重建为上述“ServerError → 用户中间件 → Exception → AsyncExitStack → 路由”的结构,具体顺序语义可参见 Middleware 教程中的“多中间件执行顺序”小节。除运行期 add_middleware() 外,还可用 Starlette 的 Middleware 类在构造 FastAPI(middleware=[...]) 时声明式传入(Middleware 已由 fastapi/middleware/init.py 从 Starlette 再导出)。

仓库自带的中间件模块一览(fastapi.middleware)

文档有一处专门的“细节说明”:下文示例中你其实也可以直接写 from starlette.middleware.something import SomethingMiddlewareFastAPI 在 fastapi.middleware 下提供这些中间件,纯粹是为了开发者便利——它们绝大多数直接来自 Starlette。这一点在源码中得到印证:fastapi/middleware/ 下的模块基本都是对 Starlette 同名类的极薄再导出:

fastapi.middleware 模块 实际来源 用途
httpsredirect.py starlette.middleware.httpsredirect.HTTPSRedirectMiddleware 强制 HTTPS/WSS
trustedhost.py starlette.middleware.trustedhost.TrustedHostMiddleware Host 头白名单校验
gzip.py starlette.middleware.gzip.GZipMiddleware GZip 响应压缩
cors.py starlette.middleware.cors.CORSMiddleware 跨域资源共享
asyncexitstack.py starlette.middleware.asyncexitstack.AsyncExitStackMiddleware 栈内资源清理
wsgi.py starlette.middleware.wsgi.WSGIMiddleware 挂载 WSGI 应用
init.py starlette.middleware.Middleware 声明式中间件组合类

CORSMiddleware 的具体用法在 CORS 教程 已有专门讲解,本节不再重复。下面按文档顺序深入三个最常用的内置中间件。

HTTPSRedirectMiddleware:强制 HTTPS/WSS 跳转

该中间件强制所有入站请求必须为 httpswss:任何以 httpws 到达的请求都会被 307 重定向到对应的安全协议。适合部署在 HTTPS 终结(如反向代理之后)场景下进一步兜底,防止明文协议被直接访问。

完整可运行示例见 docs_src/advanced_middleware/tutorial001_py310.py

from fastapi import FastAPI
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware

app = FastAPI()

app.add_middleware(HTTPSRedirectMiddleware)


@app.get("/")
async def main():
    return {"message": "Hello World"}

仓库测试如何验证它

仓库测试 tests/test_tutorial/test_advanced_middleware/test_tutorial001.py 从两个方向验证了该中间件:

  • TestClient 使用 base_url="https://testserver" 发起请求时,直接返回 200
  • 当使用默认的 http 协议请求且关闭自动跟随重定向(follow_redirects=False)时,返回状态码 307,且响应头 locationhttps://testserver/

这组用例也提醒你:该中间件生效的前提是上游真的终结了 TLS——它只负责把明文流量“导流”到安全入口,并不自己做加解密。

TrustedHostMiddleware:防御 HTTP Host 头攻击

TrustedHostMiddleware 强制所有入站请求携带正确的 Host 头,从而防御 HTTP Host Header 攻击(如密码重置钓鱼、缓存投毒等依赖篡改 Host 头的攻击手段)。若入站请求校验不通过,中间件会直接返回 400 响应。

完整示例见 docs_src/advanced_middleware/tutorial002_py310.py

from fastapi import FastAPI
from fastapi.middleware.trustedhost import TrustedHostMiddleware

app = FastAPI()

app.add_middleware(
    TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"]
)


@app.get("/")
async def main():
    return {"message": "Hello World"}

支持的构造参数

  • allowed_hosts:一个允许作为主机名的域名列表。支持通配符域名,例如 *.example.com 会匹配其所有子域名。若想允许任意主机名,要么显式传 allowed_hosts=["*"],要么干脆不挂载该中间件(因为 "*" 相当于关闭校验)。
  • www_redirect:设为 True 时,对允许主机列表中“非 www”版本域名的请求会被 307 重定向到带 www 的对应地址;默认值为 True

文档明确说明:一旦入站请求未通过校验,会收到 400 响应。

仓库测试如何验证它

test_tutorial002.py 用三种 base_url 演示了判定规则:

base_url 结果
http://example.com 200(命中白名单)
http://subdomain.example.com 200(被 *.example.com 通配匹配)
http://invalidhost 400(不在白名单)

实际接入时需要把你所有的对外域名(含可能用到的子域名)都放进 allowed_hosts,并留意 www_redirect=True 的默认重定向行为是否符合你的域名规划。

GZipMiddleware:为响应启用 GZip 压缩

GZipMiddleware 会对Accept-Encoding 请求头中包含 "gzip" 的请求返回 GZip 压缩后的响应,从而减小传输体积、降低带宽消耗。值得注意的细节是:它既能处理标准响应,也能处理流式(streaming)响应

完整示例见 docs_src/advanced_middleware/tutorial003_py310.py

from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware

app = FastAPI()

app.add_middleware(GZipMiddleware, minimum_size=1000, compresslevel=5)


@app.get("/")
async def main():
    return "somebigcontent"

支持的构造参数

  • minimum_size小于该字节数的响应不做 GZip 压缩。默认值为 500(字节)。这是为了“小响应不值得压缩”的工程权衡——压缩小响应反而可能因头部开销得不偿失。
  • compresslevel:GZip 压缩过程中使用的压缩级别,取值为 19 的整数,默认值为 9。级别越低压缩越快但产物越大,级别越高压缩越慢但产物越小。在 CPU 敏感或流量峰值场景可调低以换取吞吐。

文档示例即为“不是默认参数”的实践:minimum_size=1000(小于 1KB 不压缩)配合 compresslevel=5(速度与体积的折中)。

仓库测试如何验证它

test_tutorial003.py 为同一个 app 额外注册了一条返回 4000x 字符的路由 /large,然后断言:

  • 请求携带 accept-encoding: gzip 时响应状态为 200
  • 响应头 Content-Encoding 等于 gzip
  • 压缩后的 Content-Length 数值小于原始的 4000
  • 请求不带 gzip 编码的根路径 / 时行为正常。

如果你想亲手验证,可把任一示例保存为 main.py 后用 uvicorn main:app 启动,再配合浏览器开发者工具或 curl --compressed 观察响应头中的 Content-Encoding: gzip

其他 ASGI 中间件生态与延伸阅读

FastAPI 的中间件体系并不局限于上述三者。因为 ASGI 规范天然具备互操作性,生态里还活跃着大量同类中间件,例如:

  • Uvicorn 的 ProxyHeadersMiddleware:在反向代理(如 Nginx)之后,用于根据代理头还原客户端真实 IP 与协议信息,对日志审计、限流、HTTPS 判定等场景很重要;
  • MessagePack 等序列化类 ASGI 中间件:为需要紧凑二进制载荷的接口提供备选编解码路径;
  • Starlette 官方维护的其他中间件:如会话管理 SessionMiddleware、认证 AuthenticationMiddleware、自定义异常响应 ExceptionMiddleware 等,均在 Starlette 中间件文档中有完整说明,通常只需 from starlette.middleware.xxx import XxxMiddleware 引入后按前文方式注册即可。

需要再次强调的是:接入任何第三方 ASGI 中间件时,优先使用 app.add_middleware() 而不是手工包裹应用对象,这样你得到的中间件栈仍处于 FastAPI/Starlette 的管理之下,服务器错误兜底与自定义异常处理器都不会被绕过。这与本仓库源码中 build_middleware_stack() 的实现(fastapi/applications.py)保持一致。

小结

本文围绕 Advanced Middleware 文档 完整覆盖了三个层面的知识:

  1. 接入机制:FastAPI 基于 Starlette/ASGI,可用 app.add_middleware() 注册任意 ASGI 中间件;源码证实用户中间件位于 ServerErrorMiddleware 之内、ExceptionMiddleware 之外,因此错误处理不被绕过;
  2. 内置中间件HTTPSRedirectMiddleware(强制 HTTPS/WSS)、TrustedHostMiddlewareallowed_hosts + www_redirect,非法 Host 返回 400)、GZipMiddlewareminimum_size 默认 500、compresslevel 默认 9、范围 1–9),每个均有文档示例与仓库测试用例双保险;
  3. 生态延展fastapi.middleware 各模块实为 Starlette 同名类的再导出,此外 Uvicorn、Starlette 与 ASGI 社区还有更丰富的中间件可选用。

掌握了这些中间件与注册顺序规则,你就可以在 FastAPI 应用中可靠地叠加 HTTPS 强制、Host 校验、GZip 压缩等生产级能力,而无需担心它们破坏框架自身的异常处理链路。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388