FastAPI 高级中间件Advanced Middleware完全指南集成任意 ASGI 中间件与内置中间件实战【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi本篇技术指南以 FastAPI 高级用户指南中的 Middleware Avanzado高级中间件章节英文原版为核心系统讲解 FastAPI 项目中中间件的进阶用法如何把任意符合 ASGI 规范的第三方中间件接入应用以及仓库内置/内置集成的HTTPSRedirectMiddleware、TrustedHostMiddleware、GZipMiddleware等中间件的正确配置方式与参数语义。读完本文你将掌握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_configrainbow)用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_configrainbow)app.add_middleware()第一个参数接收中间件类其后紧跟任意需要传递给该中间件的附加参数构造参数如这里的some_configrainbow。从源码看 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 SomethingMiddleware。FastAPI 在fastapi.middleware下提供这些中间件纯粹是为了开发者便利——它们绝大多数直接来自 Starlette。这一点在源码中得到印证fastapi/middleware/下的模块基本都是对 Starlette 同名类的极薄再导出fastapi.middleware 模块实际来源用途httpsredirect.pystarlette.middleware.httpsredirect.HTTPSRedirectMiddleware强制 HTTPS/WSStrustedhost.pystarlette.middleware.trustedhost.TrustedHostMiddlewareHost 头白名单校验gzip.pystarlette.middleware.gzip.GZipMiddlewareGZip 响应压缩cors.pystarlette.middleware.cors.CORSMiddleware跨域资源共享asyncexitstack.pystarlette.middleware.asyncexitstack.AsyncExitStackMiddleware栈内资源清理wsgi.pystarlette.middleware.wsgi.WSGIMiddleware挂载 WSGI 应用init.pystarlette.middleware.Middleware声明式中间件组合类CORSMiddleware的具体用法在 CORS 教程 已有专门讲解本节不再重复。下面按文档顺序深入三个最常用的内置中间件。HTTPSRedirectMiddleware强制 HTTPS/WSS 跳转该中间件强制所有入站请求必须为https或wss任何以http或ws到达的请求都会被 307 重定向到对应的安全协议。适合部署在 HTTPS 终结如反向代理之后场景下进一步兜底防止明文协议被直接访问。完整可运行示例见 docs_src/advanced_middleware/tutorial001_py310.pyfrom 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_urlhttps://testserver发起请求时直接返回200当使用默认的http协议请求且关闭自动跟随重定向follow_redirectsFalse时返回状态码307且响应头location为https://testserver/。这组用例也提醒你该中间件生效的前提是上游真的终结了 TLS——它只负责把明文流量“导流”到安全入口并不自己做加解密。TrustedHostMiddleware防御 HTTP Host 头攻击TrustedHostMiddleware强制所有入站请求携带正确的Host头从而防御 HTTP Host Header 攻击如密码重置钓鱼、缓存投毒等依赖篡改Host头的攻击手段。若入站请求校验不通过中间件会直接返回400响应。完整示例见 docs_src/advanced_middleware/tutorial002_py310.pyfrom 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.com200命中白名单http://subdomain.example.com200被*.example.com通配匹配http://invalidhost400不在白名单实际接入时需要把你所有的对外域名含可能用到的子域名都放进allowed_hosts并留意www_redirectTrue的默认重定向行为是否符合你的域名规划。GZipMiddleware为响应启用 GZip 压缩GZipMiddleware会对在Accept-Encoding请求头中包含gzip的请求返回 GZip 压缩后的响应从而减小传输体积、降低带宽消耗。值得注意的细节是它既能处理标准响应也能处理流式streaming响应。完整示例见 docs_src/advanced_middleware/tutorial003_py310.pyfrom fastapi import FastAPI from fastapi.middleware.gzip import GZipMiddleware app FastAPI() app.add_middleware(GZipMiddleware, minimum_size1000, compresslevel5) app.get(/) async def main(): return somebigcontent支持的构造参数minimum_size小于该字节数的响应不做 GZip 压缩。默认值为500字节。这是为了“小响应不值得压缩”的工程权衡——压缩小响应反而可能因头部开销得不偿失。compresslevelGZip 压缩过程中使用的压缩级别取值为1到9的整数默认值为9。级别越低压缩越快但产物越大级别越高压缩越慢但产物越小。在 CPU 敏感或流量峰值场景可调低以换取吞吐。文档示例即为“不是默认参数”的实践minimum_size1000小于 1KB 不压缩配合compresslevel5速度与体积的折中。仓库测试如何验证它test_tutorial003.py 为同一个app额外注册了一条返回4000个x字符的路由/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 文档 完整覆盖了三个层面的知识接入机制FastAPI 基于 Starlette/ASGI可用app.add_middleware()注册任意 ASGI 中间件源码证实用户中间件位于ServerErrorMiddleware之内、ExceptionMiddleware之外因此错误处理不被绕过内置中间件HTTPSRedirectMiddleware强制 HTTPS/WSS、TrustedHostMiddlewareallowed_hostswww_redirect非法 Host 返回 400、GZipMiddlewareminimum_size默认 500、compresslevel默认 9、范围 1–9每个均有文档示例与仓库测试用例双保险生态延展fastapi.middleware各模块实为 Starlette 同名类的再导出此外 Uvicorn、Starlette 与 ASGI 社区还有更丰富的中间件可选用。掌握了这些中间件与注册顺序规则你就可以在 FastAPI 应用中可靠地叠加 HTTPS 强制、Host 校验、GZip 压缩等生产级能力而无需担心它们破坏框架自身的异常处理链路。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考