fastapi/docs/zh/docs/tutorial/middleware.md

3.9 KiB
Raw Blame History

中间件

你可以向 FastAPI 应用添加中间件。

“中间件”是一个函数,它会在每个特定的路径操作处理每个请求之前运行,也会在返回每个响应之前运行。

  • 它接收你的应用的每一个请求
  • 然后它可以对这个请求做一些事情或者执行任何需要的代码。
  • 然后它将这个请求传递给应用程序的其他部分(某个路径操作)处理。
  • 之后它获取应用程序生成的响应(由某个路径操作产生)。
  • 它可以对该响应做一些事情或者执行任何需要的代码。
  • 然后它返回这个响应

/// note | 技术细节

如果你有使用 yield 的依赖,依赖中的退出代码会在中间件之后运行。

如果有任何后台任务(会在后台任务{.internal-link target=_blank}一节中介绍,你稍后会看到),它们会在所有中间件之后运行。

///

创建中间件

要创建中间件,你可以在函数的顶部使用装饰器 @app.middleware("http")

中间件函数会接收:

  • request
  • 一个函数 call_next,它会把 request 作为参数接收。
    • 这个函数会把 request 传递给相应的路径操作
    • 然后它返回由相应路径操作生成的 response
  • 在返回之前,你可以进一步修改 response

{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}

/// tip

请记住可以使用 X- 前缀添加专有自定义请求头。

但是如果你有希望让浏览器中的客户端可见的自定义请求头,你需要把它们加到你的 CORS 配置(CORS (Cross-Origin Resource Sharing){.internal-link target=_blank})的 expose_headers 参数中,参见 Starlette 的 CORS 文档

///

/// note | 技术细节

你也可以使用 from starlette.requests import Request

FastAPI 为了开发者方便提供了该对象,但它直接来自 Starlette。

///

response 之前与之后

你可以在任何路径操作接收 request 之前,添加要与该 request 一起运行的代码。

也可以在生成 response 之后、返回之前添加代码。

例如,你可以添加一个自定义请求头 X-Process-Time,其值为处理请求并生成响应所花费的秒数:

{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}

/// tip

这里我们使用 time.perf_counter() 而不是 time.time(),因为在这类场景中它可能更精确。🤓

///

多个中间件的执行顺序

当你使用 @app.middleware() 装饰器或 app.add_middleware() 方法添加多个中间件时,每个新中间件都会包裹应用,形成一个栈。最后添加的中间件是“最外层”的,最先添加的是“最内层”的。

在请求路径上,最外层的中间件先运行。

在响应路径上,它最后运行。

例如:

app.add_middleware(MiddlewareA)
app.add_middleware(MiddlewareB)

这会产生如下执行顺序:

  • 请求MiddlewareB → MiddlewareA → 路由

  • 响应:路由 → MiddlewareA → MiddlewareB

这种栈式行为确保中间件按可预测且可控的顺序执行。

其他中间件

你可以稍后在高级用户指南:高级中间件{.internal-link target=_blank}中阅读更多关于其他中间件的内容。

你将在下一节中了解如何使用中间件处理 CORS