如何在FastAPI/Starlette中间件中通过Request对象获取路由名称?
在FastAPI/Starlette中获取路由的name属性
问题核心
你可以在FastAPI中获取路由的name,但直接在全局HTTP中间件中访问request.scope['route']会报错——因为HTTP中间件的执行时机在FastAPI完成路由匹配之前,此时scope字典里还不存在route字段。
报错原因
你提供的中间件代码中,print(request.scope['route'].name)写在call_next(request)之前,这一步还没完成路由匹配,scope里没有route键,因此触发KeyError。
解决方案
方案1:使用路由级中间件(推荐)
使用Starlette的RouterMiddleware,它会在路由匹配完成后执行,此时可以直接访问request.scope['route'].name:
from fastapi import FastAPI, Request from starlette.middleware.base import RouterMiddleware, RequestResponseEndpoint app = FastAPI() class RouteLogger: async def __call__(self, request: Request, call_next: RequestResponseEndpoint): # 路由已匹配,直接获取name route_name = request.scope['route'].name print(f"当前访问的路由名称: {route_name}") response = await call_next(request) return response # 给应用的路由器添加该中间件 app.router.add_middleware(RouterMiddleware, dispatch=RouteLogger()) # 测试路由 @app.get('/services/{service}', name="abc") async def list_services(service: str) -> dict: return {"service_id": service} @app.get('/', name='home') async def home(request: Request): return {"current_route": request.scope['route'].name}
方案2:通过依赖项+请求状态传递(兼容全局HTTP中间件)
如果必须使用全局HTTP中间件,可以在路由的依赖项中获取路由名称并存储到request.state,再在中间件的call_next之后读取:
from fastapi import FastAPI, Request, Depends app = FastAPI() def save_route_name(request: Request): # 路由匹配完成后,将name存入请求状态 request.state.route_name = request.scope['route'].name return request.state.route_name @app.middleware("http") async def logging_middleware(request: Request, call_next): response = await call_next(request) # 路由处理完成后,从state中读取name if hasattr(request.state, 'route_name'): print(f"路由名称: {request.state.route_name}") return response # 给需要监控的路由添加依赖 @app.get('/services/{service}', name="abc", dependencies=[Depends(save_route_name)]) async def list_services(service: str) -> dict: return {"service_id": service} @app.get('/', name='home', dependencies=[Depends(save_route_name)]) async def home(request: Request): return {"current_route": request.scope['route'].name}
额外说明
在视图函数中直接访问request.scope['route'].name是完全可行的,因为视图函数的执行时机在路由匹配之后,此时scope中已经包含了匹配到的路由对象。
内容的提问来源于stack exchange,提问作者Devendra Singh khurana
相关产品推荐
相关产品推荐

