跳到内容

中间件

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

“中间件” 是一个函数,它在每个 **请求** 被特定 *路径操作* 处理 **之前**,以及在每个 **响应** 返回 **之前**,都会执行。

  • 它会处理进入应用的每个 **请求**。
  • 然后,它可以对该 **请求** 做一些处理,或运行任何需要的代码。
  • 接着,它将 **请求** 传递给应用程序的其余部分(由某个 *路径操作* 处理)。
  • 然后,它会获取由应用程序(由某个 *路径操作*)生成的 **响应**。
  • 它可以对该 **响应** 做一些处理,或运行任何需要的代码。
  • 最后,它返回该 **响应**。

技术细节

如果你的依赖项带有 yield,退出代码将在中间件 *之后* 运行。

如果有任何后台任务(在 后台任务 部分有介绍,你稍后会看到),它们将在所有中间件 *之后* 运行。

创建一个中间件

要创建一个中间件,你需要在函数上方使用 @app.middleware("http") 装饰器。

中间件函数接收:

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

from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.perf_counter()
    response = await call_next(request)
    process_time = time.perf_counter() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response

提示

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

但如果你有自定义请求头,并希望浏览器中的客户端能够看到它们,你需要将它们添加到你的 CORS 配置中(CORS (跨域资源共享)),使用 Starlette 的 CORS 文档中记录的 expose_headers 参数。

技术细节

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

FastAPI 提供了它以方便开发者。但它直接来自 Starlette。

response 之前和之后

你可以在任何 *路径操作* 接收到 request 之前,添加要对 request 运行的代码。

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

例如,你可以添加一个自定义请求头 X-Process-Time,其中包含处理请求和生成响应所花费的时间(以秒为单位):

import time

from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.perf_counter()
    response = await call_next(request)
    process_time = time.perf_counter() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response

提示

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

多个中间件的执行顺序

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

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

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

例如

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

这导致了以下执行顺序:

  • 请求:中间件B → 中间件A → 路由

  • 响应:路由 → 中间件A → 中间件B

这种堆叠行为确保了中间件以可预测且可控的顺序执行。

其他中间件

你可以在稍后的高级用户指南:高级中间件中阅读有关其他中间件的更多信息。

在下一节中,你将读到如何通过中间件处理 CORS