首页
/ FastAPI 高级中间件完全指南:ASGI 中间件接入与 HTTPSRedirect、TrustedHost、GZip 的实战用法

FastAPI 高级中间件完全指南:ASGI 中间件接入与 HTTPSRedirect、TrustedHost、GZip 的实战用法

2026-09-07 20:02:47作者:秋阔奎Evelyn

FastAPI 基于 Starlette 构建并完整实现了 ASGI 规范,因此你可以在应用中接入任何符合 ASGI 规范的中间件。本篇指南以 官方文档 docs/fr/docs/advanced/middleware.md 为核心骨架,系统讲解如何用 app.add_middleware() 优雅地接入第三方 ASGI 中间件,并深入剖析 FastAPI 内置的 HTTPSRedirectMiddlewareTrustedHostMiddlewareGZipMiddleware 三个高频中间件的参数含义、默认值与底层实现。读完本篇,你将能独立完成 HTTPS 强制跳转、Host 头攻击防护与响应 GZip 压缩的配置,并能正确评估任意 ASGI 中间件在当前项目中的接入方式。

1. 知识前提:从自定义中间件与 CORS 谈起

在深入高级中间件之前,请确保你已经掌握两类基础用法:

本节内容是它们在"通用 ASGI 中间件生态"维度的延伸——FastAPI 自带的基础教程只覆盖了少量场景,而真实生产环境还需要考虑安全跳转、Host 校验、传输压缩等能力,这些正是本篇要解决的核心问题。

2. 接入任意 ASGI 中间件:app.add_middleware()

2.1 为什么任何 ASGI 中间件都可以用

因为 FastAPI 基于 Starlette 且实现了 ASGI 规范,所以只要一个中间件遵循 ASGI 规范,它就不必专门为 FastAPI 或 Starlette 定制,也能直接工作。

通常,ASGI 中间件被设计为一个"类",其构造函数期待第一个参数是一个 ASGI 应用对象。因此第三方 ASGI 中间件的文档通常会引导你写成下面的包装(wrap)风格

from unicorn import UnicornMiddleware

app = SomeASGIApp()

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

这种写法确实可行,但 FastAPI(实际上是其底层的 Starlette)提供了更简洁、更安全的接入方式——app.add_middleware()(就像你在 CORS 示例中看到的那样):

from fastapi import FastAPI
from unicorn import UnicornMiddleware

app = FastAPI()

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

app.add_middleware() 接收一个中间件类作为第一个参数,之后的所有关键字参数都会被原样传给该中间件的构造函数。

2.2 为什么推荐 add_middleware() 而不是手动包装

从源码看,原因非常明确。在 fastapi/applications.py 中,FastAPI 把构造时传入的 middleware 保存在 self.user_middleware 列表里,并在 build_middleware_stack() 中把它嵌入一条精心编排的中间件链路:

ServerErrorMiddleware(服务器错误兜底)
    └─ 用户通过 add_middleware 挂载的自定义中间件
        └─ ExceptionMiddleware(异常处理分发)
            └─ AsyncExitStackMiddleware(FastAPI 专用,负责关闭文件等资源)
                └─ 真正的路由处理(Router)

也就是说,FastAPI 会自动保证

  • 内部 ServerErrorMiddleware 能捕获并处理服务器错误(500),即使错误发生在你的自定义中间件内部;
  • 你注册的自定义异常处理器(如覆盖 HTTPException、校验错误)能够在正确的位置被触发;
  • FastAPI 特有的 AsyncExitStackMiddleware 位于自定义中间件之后,用于正确关闭响应文件等资源、维持 contextvars 上下文。

如果采用手工 SomeMiddleware(app) 的包装方式,你就需要自己维护这套链路顺序,很容易把错误处理与异常分发放在错误的位置,导致中间件中的异常无法被正确转为响应。这正是文档强调"内部中间件处理服务器错误、自定义异常处理器正常工作"的底层保障。

3. 内置中间件:fastapi.middleware 模块导览

FastAPI 为常见的应用场景内置了一批中间件。一个值得注意的技术细节是:下面的示例你同样可以写成 from starlette.middleware.something import SomethingMiddleware

FastAPI 在 fastapi.middleware 下提供这些中间件,仅仅是为了方便开发者统一从 fastapi 导入,而其中绝大多数实现直接来自 Starlette。打开仓库 fastapi/middleware 目录即可看到实际文件:

文件 内容
httpsredirect.py 从 Starlette 再导出的 HTTPSRedirectMiddleware
trustedhost.py 从 Starlette 再导出的 TrustedHostMiddleware
gzip.py 从 Starlette 再导出的 GZipMiddleware
cors.py 从 Starlette 再导出的 CORSMiddleware
wsgi.py 用于挂载 WSGI 应用的中间件
asyncexitstack.py FastAPI 内部使用的 AsyncExitStackMiddleware

fastapi/middleware/httpsredirect.py 为例,它整个文件本质上只是:

from starlette.middleware.httpsredirect import (  # noqa
    HTTPSRedirectMiddleware as HTTPSRedirectMiddleware,
)

所以"FastAPI 内置中间件"与"Starlette 中间件"在实现层面是同一份代码,导入路径不同而已。

下面逐一介绍三个最常用的安全与性能类中间件。

4. HTTPSRedirectMiddleware:强制 HTTPS / WSS 访问

4.1 作用

HTTPSRedirectMiddleware 强制所有进入应用的请求必须是 httpswss 协议;任何以 httpws 发起的请求,都会被重定向到对应的安全协议(HTTP 响应码为 307 临时重定向)。

4.2 完整可运行示例

下面的完整示例来自 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"}

4.3 使用场景与注意事项

  • 该中间件没有额外配置参数,注册即生效;
  • 典型应用场景是生产环境已终止 TLS(如在 Nginx、反向代理、负载均衡层解密 HTTPS)后,在应用层兜底,确保即使客户端绕过代理直连应用,也不会通过明文 HTTP 传输数据;
  • 需要留意:一旦开启,本地开发若直接以 http://127.0.0.1:8000 访问,请求会被持续重定向到 https:// 而无法到达路由——因此通常只在生产配置中启用,或配合环境判断按需注册。

5. TrustedHostMiddleware:校验 Host 头,抵御 Host 头攻击

5.1 作用

TrustedHostMiddleware 强制所有进入请求的 Host 头必须被正确设置且在允许名单内,用于抵御 HTTP Host Header 攻击(例如密码重置投毒、缓存污染等依赖伪造 Host 头的攻击)。一旦校验失败,中间件会直接返回 400 Bad Request 响应。

5.2 完整可运行示例

完整示例来自 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"}

5.3 支持的参数

参数 类型与说明 默认值
allowed_hosts 允许作为主机名的域名列表。支持通配符域名(如 *.example.com 用于匹配所有子域名)。若要放行任意主机名,可设为 allowed_hosts=["*"],或者干脆不挂载该中间件 必填
www_redirect 设为 True 时,对允许主机名"非 www 版本"的请求会重定向到其对应的"www 版本" True

例如,配置了 allowed_hosts=["example.com", "*.example.com"] 后:

  • example.com 与任意子域(a.example.comb.example.com…)均被放行;
  • 由于默认 www_redirect=True,对 www.example.com 的访问会被保留,而对裸域与子域之间的差异按重定向策略处理;
  • 其他任意 Host(如 evil.com)都会收到 400 响应。

5.4 实战建议

在部署于云负载均衡 / Kubernetes Ingress 等环境时,务必把域名白名单写全(主域名加 *. 通配),否则健康检查或服务间调用可能因 Host 校验不过而收到 400,造成误判宕机。反过来,若服务会被许多随机域名访问(如某些内部探活场景),则需显式使用 ["*"] 或移除该中间件。

6. GZipMiddleware:为响应开启 GZip 压缩

6.1 作用

GZipMiddleware 会为所有在 Accept-Encoding 请求头中包含 "gzip" 的请求,对响应体进行 GZip 压缩。它同时支持普通响应与流式响应(streaming responses)

6.2 完整可运行示例

完整示例来自 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"

6.3 支持的参数

参数 类型与说明 默认值
minimum_size 小于该字节数的响应不做 GZip 压缩(避免小响应因压缩头反而变大) 500
compresslevel GZip 压缩级别,取 1~9 的整数。值越小压缩越快但文件更大;值越大压缩越慢但文件更小 9

6.4 设计细节与权衡

  • minimum_size 的用意:对几十字节的小 JSON 响应做 GZip 没有收益(甚至因增加压缩元数据而变大),默认 500 字节的阈值能避免这种浪费;
  • compresslevel 的权衡:压缩级别本质是"CPU 时间 vs 带宽"的交换。高流量场景若 CPU 吃紧,可适当调低(如 5~6)以降低延迟;追求极致带宽节省时维持高位;
  • 源码中 FastAPI 对 gzip.py 只是从 Starlette 原样再导出,因此压缩算法实现细节与 Starlette 保持一致。

需要提醒:如果上游(如 Nginx、CDN)已经开启了 gzip,应用层再叠加压缩会造成双重压缩,通常建议二者只保留其一。

7. 其他 ASGI 中间件:生态远不止这些

ASGI 生态中还存在大量其他中间件,例如文档中列举的典型代表:

  • Uvicorn 的 ProxyHeadersMiddleware(位于 uvicorn.middleware.proxy_headers 模块):用于解析反向代理设置的 X-Forwarded-* 头,正确还原客户端 IP 与协议。当你把 FastAPI 部署在 Nginx / Traefik 之后时,它与本文第 4、5 节的 HTTPS/Host 处理配合使用尤为关键;
  • MessagePack(msgpack-asgi):提供基于 MessagePack 二进制序列化协议的请求/响应支持。

文档还建议通过以下两个渠道发现更多可用中间件:Starlette 官方中间件文档(覆盖 Session、Authentication、CORSMiddleware、BaseHTTPMiddleware 等)以及社区整理的 ASGI Awesome 列表。接入这些第三方中间件时,统一使用 app.add_middleware() 即可获得本文第 2.2 节所述的错误处理与异常分发保障。

8. 小结:三种内置中间件的选型速查

中间件 核心职责 关键参数 典型场景
HTTPSRedirectMiddleware 强制 https/wsshttp/ws 自动 307 跳转 生产环境强制加密访问
TrustedHostMiddleware 校验 Host 头合法性,非法返回 400 allowed_hosts(支持 *. 通配)、www_redirect(默认 True 抵御 HTTP Host Header 攻击
GZipMiddleware Accept-Encoding: gzip 对响应(含流式)做压缩 minimum_size(默认 500)、compresslevel(默认 9,范围 1~9) 降低大响应传输体积

三者均从 fastapi.middleware 导入(实现来自 Starlette),注册方式统一为 app.add_middleware(SomeMiddleware, **options)。借助 fastapi/applications.py 中的 build_middleware_stack(),这些用户中间件会被正确嵌入 ServerErrorMiddlewareExceptionMiddleware 之间,从而保证错误兜底与自定义异常处理器始终生效——这也是在生产中放心叠加中间件的关键前提。

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

项目优选

收起
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