中间件¶
你可以向 FastAPI 应用添加中间件。
“中间件” 是一个函数,它在每个 **请求** 被特定 *路径操作* 处理 **之前**,以及在每个 **响应** 返回 **之前**,都会执行。
- 它会处理进入应用的每个 **请求**。
- 然后,它可以对该 **请求** 做一些处理,或运行任何需要的代码。
- 接着,它将 **请求** 传递给应用程序的其余部分(由某个 *路径操作* 处理)。
- 然后,它会获取由应用程序(由某个 *路径操作*)生成的 **响应**。
- 它可以对该 **响应** 做一些处理,或运行任何需要的代码。
- 最后,它返回该 **响应**。
创建一个中间件¶
要创建一个中间件,你需要在函数上方使用 @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。