如何在FastAPI的router.post中捕获中间件生成的唯一ID?
解决FastAPI中间件生成的请求ID在路由中获取的问题
问题原因
中间件里生成的idem是局部变量,路由函数的作用域无法直接访问该变量,直接引用会触发"未定义变量"的错误。
解决方案
1. 修改中间件,将请求ID存入Request对象的state属性
Starlette的Request对象自带state属性,可用来存储当前请求生命周期内的自定义数据。修改后的中间件代码如下:
import string, time, random, logging from starlette.requests import Request @app.middleware("http") async def log_requests(request: Request, call_next): idem = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6)) # 将请求ID存入request.state,供后续路由使用 request.state.idem = idem logger.info(f"rid={idem} start request path={request.url.path}") start_time = time.time() response = await call_next(request) process_time = (time.time() - start_time) * 1000 formatted_process_time = '{0:.2f}'.format(process_time) logger.info(f"rid={idem} completed_in={formatted_process_time}ms status_code={response.status_code}") return response
2. 在路由函数中注入Request对象并获取请求ID
在路由函数的参数中添加Request对象的依赖注入,然后从request.state中取出之前存入的idem:
import logging as log from starlette.requests import Request from fastapi import Body, APIRouter router = APIRouter() @router.post("/infer/", response_description="AD Data Infer") async def ad_infer_algorithm( ad_infer_config: ADInferConfigSchema = Body(...), request: Request # 注入当前请求的Request对象 ): # 从request.state中获取请求ID idem = request.state.idem log.info(f"Executing AD Train Algorithm with config, rid={idem}") return "2"
可选优化:封装请求ID依赖项
如果多个路由都需要使用请求ID,可以封装成独立的依赖项,避免重复代码:
from fastapi import Depends, Request def get_request_id(request: Request): return request.state.idem # 路由中使用封装后的依赖 @router.post("/infer/") async def ad_infer_algorithm( ad_infer_config: ADInferConfigSchema = Body(...), idem: str = Depends(get_request_id) ): log.info(f"Executing AD Train Algorithm with config, rid={idem}") return "2"
内容的提问来源于stack exchange,提问作者utkarsh saraf
相关产品推荐
相关产品推荐

