FastAPI如何将include_router的dependencies返回值传递给子路由
FastAPI 路由级依赖返回值透传解决方案
你遇到的问题本质是:FastAPI 中通过include_router的dependencies参数传入的全局路由依赖,仅会执行依赖的校验逻辑,返回值会被默认丢弃,无法直接被下层路径函数接收。以下是两种生产环境常用的实现方案:
方案1:请求上下文存储(推荐)
通过 FastAPI 提供的Request对象的state属性存储 JWT 解码结果,子路由按需取值即可,无需修改原有路由挂载的逻辑,也不会重复执行依赖校验。
步骤1:修改依赖函数,把 payload 存入请求上下文
修改main.py中的authenticate_and_decode_JWT函数:
from typing import Optional from jose import jwt # 新增导入Request from fastapi import FastAPI, Depends, Header, HTTPException, status, Request from jose.exceptions import JWTError from routers import books app = FastAPI() def authenticate_and_decode_JWT(request: Request, x_token: str = Header(None)): # 补充参数校验,避免空token时split报错 if not x_token or not x_token.startswith("Bearer "): raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED) try: payload = jwt.decode(x_token.split(' ')[1], 'secret key', algorithms=['HS256']) # 把解码结果存入请求上下文,全链路可访问 request.state.jwt_payload = payload return payload except JWTError: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED) # 原有路由挂载逻辑无需修改 app.include_router( books.router, prefix="/books", dependencies=[Depends(authenticate_and_decode_JWT)], ) @app.get("/") def read_root(): return {"Hello": "World"}
步骤2:子路由中获取 payload
可以直接注入Request对象取值,也可以封装单独的取值依赖简化代码:
直接取值写法(routers/books.py)
from fastapi import APIRouter, Request router = APIRouter() @router.get('/') def get_book(request: Request): payload = request.state.jwt_payload # 直接使用payload中的用户信息即可 pass @router.post('/') def create_book(request: Request): payload = request.state.jwt_payload pass
封装取值依赖写法(更简洁)
首先在公共依赖文件(或main.py)中封装取值逻辑:
def get_jwt_payload(request: Request) -> dict: return request.state.jwt_payload
之后子路由接口直接注入该依赖即可:
from fastapi import APIRouter, Depends # 导入封装的取值依赖 from main import get_jwt_payload router = APIRouter() @router.get('/') def get_book(payload: dict = Depends(get_jwt_payload)): # 直接使用payload pass @router.post('/') def create_book(payload: dict = Depends(get_jwt_payload)): pass
方案2:子路由层面声明依赖
如果不想用请求上下文存储,也可以直接把JWT校验依赖作为子路由路径函数的通用参数,FastAPI会自动复用依赖的执行结果,不会重复校验:
# routers/books.py from fastapi import APIRouter, Depends from main import authenticate_and_decode_JWT router = APIRouter() @router.get('/') def get_book(payload: dict = Depends(authenticate_and_decode_JWT)): pass @router.post('/') def create_book(payload: dict = Depends(authenticate_and_decode_JWT)): pass
这种写法下可以把include_router中声明的依赖去掉,避免重复声明。适合仅部分子路由接口需要用到payload的场景。
内容的提问来源于stack exchange,提问作者neilZon
相关产品推荐
相关产品推荐

