You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:46:07