FastAPI(37)- Middleware 中间件
FastAPI(37)- Middleware 中间件
什么是中间件
- 就是一个函数,它在被任何特定路径操作处理之前处理每个请求,且在每个 response 返回之前被调用
- 类似钩子函数
执行顺序
- 中间件会接收应用程序中的每个请求 Request
- 针对请求 Request 或其他功能,可以自定义代码块
- 再将请求 Request 传回路径操作函数,由应用程序的其余部分继续处理该请求
- 路径操作函数处理完后,中间件会获取到应用程序生成的响应 Response
- 中间件可以针对响应 Response 或其他功能,又可以自定义代码块
- 最后返回响应 Response 给客户端
Request
FastAPI 有提供 Request 模块,但其实就是 starlette 里面的 Request
Response
FastAPI 有提供 Response 模块,但其实就是 starlette 里面的 Response
中间件和包含 yield 的依赖项、Background task 的执行顺序
- 依赖项 yield 语句前的代码块
- 中间件
- 依赖项 yield 语句后的代码块
- Background task
创建中间件
import time
from fastapi import FastAPI, Request
@app.middleware("http")
# 必须用 async
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
# 必须用 await
response = await call_next(request)
process_time = time.time() - start_time
# 自定义请求头
response.headers["X-Process-Time"] = str(process_time)
# 返回响应
return response
中间件函数接收两个参数
- request:Request 请求,其实就是 starlette 库里面的 Request
- call_next:是一个函数,将 request 作为参数
call_next
- 会将 request 传递给相应的路径操作函数
- 然后会返回路径操作函数产生的响应,赋值给 response
- 可以在中间件 return 前对 response 进行操作
实际栗子
import uvicorn
from fastapi import FastAPI, Request, Query, Body, status
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
app = FastAPI()
@app.middleware("http")
# 必须用 async
async def add_process_time_header(request: Request, call_next):
# 1、可针对 Request 或其他功能,自定义代码块
print("=== 针对 request 或其他功能执行自定义逻辑代码块 ===")
print(request.query_params)
print(request.method)
# 2、将 Request 传回给对应的路径操作函数继续处理请求
# 必须用 await
response = await call_next(request)
# 4、接收到路径操作函数所产生的的 Response,记住这并不是返回值(return)
# 5、可针对 Response 或其他功能,自定义代码块
print("*** 针对 response 或其他功能执行自定义逻辑 ***")
# 自定义请求头响应状态码
response.headers["X-Process-Token"] = str("test_token_polo")
response.status_code = status.HTTP_202_ACCEPTED
# 6、最终返回 Response 给客户端
return response
class User(BaseModel):
name: str = None
age: int = None
@app.post("/items/")
async def read_item(item_id: str = Query(...), user: User = Body(...)):
# 3、收到请求,处理请求
res = {"item_id": item_id}
if user:
res.update(jsonable_encoder(user))
print("@@@ 执行路径操作函数 @@@", res)
# 有没有 return 都不影响中间件接收 Response
return res
重点
- call_next 是一个函数,调用的就是请求路径对应的路径操作函数
- 返回值是一个 Response 类型的对象
访问 /items ,控制台输出结果
=== 针对 request 或其他功能执行自定义逻辑代码块 ===
item_id=test
POST
@@@ 执行路径操作函数 @@@ {'item_id': 'test', 'name': 'string', 'age': 0}
*** 针对 response 或其他功能执行自定义逻辑 ***
从请求结果再看执行流程图
- 黄色块就是业务代码啦
- 红色线就是处理完 Request,准备返回 Response 了
正常传参的请求结果
自定义的请求头和响应码已经生效啦
分类:
fastapi
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!