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

FastAPI中如何为同一端点添加不同路由类的多个路由器?

FastAPI 同一端点多路由类支持问题

问题场景

现有一个 /users 路由,初始化默认路由器时指定了用于翻译的 LocalizationRoute:

api_router = APIRouter(
    responses={},
    route_class=LocalizationRoute,
    dependencies=[],
)

现在需要为该路由添加日志功能,已实现基于 APIRoute 的 LoggingRoute 类:

def log_info(req_body, res_body):
    print(req_body)
    print(res_body)


class LoggingRoute(APIRoute):
    def get_route_handler(self) -> Callable:
        original_route_handler = super().get_route_handler()

        async def custom_route_handler(request: Request) -> Response:
            req_body = await request.body()
            response = await original_route_handler(request)

            if isinstance(response, StreamingResponse):
                res_body = b''
                async for item in response.body_iterator:
                    res_body += item

                task = BackgroundTask(log_info, req_body, res_body)
                return Response(content=res_body, status_code=response.status_code,
                                headers=dict(response.headers), media_type=response.media_type, background=task)
            else:
                res_body = response.body
                response.background = BackgroundTask(log_info, req_body, res_body)
                return response

        return custom_route_handler

尝试通过 api_router.include_router(APIRouter(router_class=LoggingRoute)) 挂载日志路由器,但未生效,端点仍使用 LocalizationRoute,因此疑问:FastAPI 是否支持为同一端点添加不同路由类的多个路由器?

解答

FastAPI不支持为同一端点直接叠加多个路由类。原因是:路由器的 route_class 是实例级属性,当用 include_router 挂载子路由器时,子路由器的 route_class 会被忽略,所有端点都会沿用父路由器的路由类生成处理逻辑。

可行解决方案

1. 组合路由类功能

将 LocalizationRoute 和 LoggingRoute 的逻辑合并到一个自定义路由类中,通过继承实现功能叠加:

def log_info(req_body, res_body):
    print(req_body)
    print(res_body)

class LoggingLocalizationRoute(LocalizationRoute):
    def get_route_handler(self) -> Callable:
        # 先获取本地化路由的原始处理器
        original_route_handler = super().get_route_handler()

        async def custom_route_handler(request: Request) -> Response:
            req_body = await request.body()
            response = await original_route_handler(request)

            if isinstance(response, StreamingResponse):
                res_body = b''
                async for item in response.body_iterator:
                    res_body += item

                task = BackgroundTask(log_info, req_body, res_body)
                return Response(content=res_body, status_code=response.status_code,
                                headers=dict(response.headers), media_type=response.media_type, background=task)
            else:
                res_body = response.body
                response.background = BackgroundTask(log_info, req_body, res_body)
                return response

        return custom_route_handler

然后用这个组合类初始化路由器:

api_router = APIRouter(
    responses={},
    route_class=LoggingLocalizationRoute,
    dependencies=[],
)

2. 改用中间件实现日志

如果日志功能不需要与路由类强绑定,可使用 FastAPI 的中间件实现,与 LocalizationRoute 共存:

from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware

class LoggingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next) -> Response:
        req_body = await request.body()
        response = await call_next(request)
        
        # 处理流式响应
        if isinstance(response, StreamingResponse):
            res_body = b''
            async for chunk in response.body_iterator:
                res_body += chunk
            # 重新构建响应
            response = Response(
                content=res_body,
                status_code=response.status_code,
                headers=dict(response.headers),
                media_type=response.media_type
            )
        else:
            res_body = response.body
        
        # 后台执行日志任务
        response.background = BackgroundTask(log_info, req_body, res_body)
        return response

# 给目标路由器添加中间件
api_router.add_middleware(LoggingMiddleware)

内容的提问来源于stack exchange,提问作者svs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:55:25