FastAPI中如何从middleware传递对象至endpoint?
FastAPI中间件传递对象至端点的实现方案与全局变量风险分析
一、能不能实现中间件创建对象并在端点访问?
你的第一个示例代码行不通,因为myObject是中间件函数里的局部变量,端点函数read_root根本碰不到它。不过FastAPI有标准方法能实现这个需求——用Request对象的state属性。
二、正确实现方式
把请求专属的对象存在request.state里就行,每个请求的state都是独立的,不会和其他请求串数据,代码示例如下:
from fastapi import FastAPI, Request app = FastAPI() class MyClass: def __init__(self, request: Request): self.request = request def build_data(self, arg: str): return f"处理后的参数:{arg},请求路径:{self.request.url.path}" @app.middleware("http") async def add_process_time_header(request: Request, call_next): # 将自定义对象存入request.state request.state.my_object = MyClass(request) response = await call_next(request) return response @app.get("/") def read_root(arg: str, request: Request): # 从request.state取出对象使用 data = request.state.my_object.build_data(arg) return {"Hello": "World", "data": data}
注意:
- 每个请求的
request.state是隔离的,所以存在里面的MyClass实例只会属于当前请求 - 端点函数必须声明
Request参数,才能访问state里的内容
三、全局变量方式的问题
你写的全局变量示例在多请求并发时会出大问题:
- FastAPI用的ASGI服务器(比如Uvicorn)默认会开多个进程或线程处理请求,全局的
myObject是所有请求共享的 - 当多个请求同时调用
myObject.use_request(request)和build_data时,会出现线程不安全的情况:前一个请求的request还没处理完,就被后一个请求覆盖了,导致build_data拿到错误的请求数据,逻辑完全混乱 - 这种方式绝对不能用来处理请求相关的数据,完全不适合并发场景
总结:别用全局对象存请求级数据,老老实实使用request.state传递对象才是正确做法。
内容的提问来源于stack exchange,提问作者Roman Gelembjuk
相关产品推荐
相关产品推荐

