当前位置:   article > 正文

FastAPI(37)- Middleware 中间件

app.middleware

什么是中间件

  • 就是一个函数,它在被任何特定路径操作处理之前处理每个请求,且在每个 response 返回之前被调用
  • 类似钩子函数
执行顺序
  1. 中间件会接收应用程序中的每个请求 Request
  2. 针对请求 Request 或其他功能,可以自定义代码块
  3. 再将请求 Request 传回路径操作函数,由应用程序的其余部分继续处理该请求
  4. 路径操作函数处理完后,中间件会获取到应用程序生成的响应 Response
  5. 中间件可以针对响应 Response 或其他功能,又可以自定义代码块
  6. 最后返回响应 Response 给客户端
Request

FastAPI 有提供 Request 模块,但其实就是 starlette 里面的 Request

Response

FastAPI 有提供 Response 模块,但其实就是 starlette 里面的 Response

中间件和包含 yield 的依赖项、Background task 的执行顺序
  1. 依赖项 yield 语句前的代码块
  2. 中间件
  3. 依赖项 yield 语句后的代码块
  4. Background task

创建中间件

  1. import time
  2. from fastapi import FastAPI, Request
  3. @app.middleware("http")
  4. # 必须用 async
  5. async def add_process_time_header(request: Request, call_next):
  6. start_time = time.time()
  7. # 必须用 await
  8. response = await call_next(request)
  9. process_time = time.time() - start_time
  10. # 自定义请求头
  11. response.headers["X-Process-Time"] = str(process_time)
  12. # 返回响应
  13. return response
中间件函数接收两个参数
  • request:Request 请求,其实就是 starlette 库里面的 Request
  • call_next:是一个函数,将 request 作为参数
call_next
  • 会将 request 传递给相应的路径操作函数
  • 然后会返回路径操作函数产生的响应,赋值给 response
  • 可以在中间件 return 前对 response 进行操作

实际栗子

  1. import uvicorn
  2. from fastapi import FastAPI, Request, Query, Body, status
  3. from fastapi.encoders import jsonable_encoder
  4. from pydantic import BaseModel
  5. app = FastAPI()
  6. @app.middleware("http")
  7. # 必须用 async
  8. async def add_process_time_header(request: Request, call_next):
  9. # 1、可针对 Request 或其他功能,自定义代码块
  10. print("=== 针对 request 或其他功能执行自定义逻辑代码块 ===")
  11. print(request.query_params)
  12. print(request.method)
  13. # 2、将 Request 传回给对应的路径操作函数继续处理请求
  14. # 必须用 await
  15. response = await call_next(request)
  16. # 4、接收到路径操作函数所产生的的 Response,记住这并不是返回值(return)
  17. # 5、可针对 Response 或其他功能,自定义代码块
  18. print("*** 针对 response 或其他功能执行自定义逻辑 ***")
  19. # 自定义请求头响应状态码
  20. response.headers["X-Process-Token"] = str("test_token_polo")
  21. response.status_code = status.HTTP_202_ACCEPTED
  22. # 6、最终返回 Response 给客户端
  23. return response
  24. class User(BaseModel):
  25. name: str = None
  26. age: int = None
  27. @app.post("/items/")
  28. async def read_item(item_id: str = Query(...), user: User = Body(...)):
  29. # 3、收到请求,处理请求
  30. res = {"item_id": item_id}
  31. if user:
  32. res.update(jsonable_encoder(user))
  33. print("@@@ 执行路径操作函数 @@@", res)
  34. # 有没有 return 都不影响中间件接收 Response
  35. return res
重点
  • call_next 是一个函数,调用的就是请求路径对应的路径操作函数
  • 返回值是一个 Response 类型的对象
访问 /items ,控制台输出结果
  1. === 针对 request 或其他功能执行自定义逻辑代码块 ===
  2. item_id=test
  3. POST
  4. @@@ 执行路径操作函数 @@@ {'item_id': 'test', 'name': 'string', 'age': 0}
  5. *** 针对 response 或其他功能执行自定义逻辑 ***
从请求结果再看执行流程图

  • 黄色块就是业务代码啦
  • 红色线就是处理完 Request,准备返回 Response 了
正常传参的请求结果

自定义的请求头和响应码已经生效啦

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/995081
推荐阅读
相关标签
  

闽ICP备14008679号