FastAPI中返回值的上下文管理器依赖可否设置为全局使用?
结论
FastAPI中通过app.include_router的dependencies参数、或者全局app.dependencies配置的依赖,返回值会被默认丢弃,无法直接被路径操作函数获取。但可以通过两种变通方案实现类似全局依赖的效果,避免每个路径操作重复写完整依赖声明。
方案1:将客户端实例存入request.state
修改依赖函数,把生成的AsyncClient挂载到请求对象的state属性上,全局依赖正常注册后,路径操作直接从request中读取实例即可。同时依赖可以自动从请求头解析token,无需手动传参。
修改后的依赖代码:
from fastapi import Request, Header import httpx async def get_client(request: Request, authorization: str = Header(alias="Authorization")): # 从请求头提取Bearer token token = authorization.removeprefix("Bearer ") client = httpx.AsyncClient(headers={"Authorization": f"Bearer {token}"}) try: # 将客户端实例挂载到请求对象的state属性 request.state.client = client yield client finally: # 响应返回后自动关闭客户端 await client.aclose()
路由注册代码(注意dependencies参数接收的是依赖列表):
app.include_router( router, prefix="/api", dependencies=[Depends(get_client)] )
路径操作代码,无需再单独声明依赖:
@router.get("/", status_code=status.HTTP_200_OK) async def get_something(request: Request): # 直接从state中读取复用的客户端实例,httpx异步方法需要加await resp = await request.state.client.get('https://www.google.com')
方案2:用Annotated类型别名简化依赖声明
如果不想操作request对象,也可以通过类型别名减少冗余代码,虽然仍需要在路径操作参数中声明,但代码量极低,同时保留完整的类型提示:
from typing import Annotated import httpx from fastapi import Depends # 定义依赖的类型别名,仅需声明一次 Client = Annotated[httpx.AsyncClient, Depends(get_client)] # 路径操作直接使用别名即可 @router.get("/", status_code=status.HTTP_200_OK) async def get_something(client: Client): resp = await client.get('https://www.google.com')
内容的提问来源于stack exchange,提问作者anjuna47
相关产品推荐
相关产品推荐

