[Python] FastAPI Global Timeout Middleware Not Working for Sync Routes

Discussão em 'Python' iniciado por Stack, Março 11, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to enforce a global request timeout in my FastAPI application using a custom TimeoutMiddleware. The middleware is supposed to cancel any request that takes longer than the specified timeout.

    Here is my TimeoutMiddleware implementation:

    from starlette.middleware.base import BaseHTTPMiddleware
    from fastapi import FastAPI, Request
    from starlette.responses import JSONResponse
    import asyncio

    class TimeoutMiddleware(BaseHTTPMiddleware):
    def __init__(self, app, timeout: int = 5):
    super().__init__(app)
    self.timeout = timeout

    async def dispatch(self, request: Request, call_next):
    try:
    response = await asyncio.wait_for(call_next(request), timeout=self.timeout)
    return response
    except asyncio.TimeoutError:
    return JSONResponse(status_code=408, content={"detail": "Request Timeout"})

    def create_app(routers, timeout: int = 2) -> FastAPI:
    app = FastAPI()
    app.add_middleware(TimeoutMiddleware, timeout=timeout)
    for router, prefix in routers:
    app.include_router(router, prefix=prefix)
    return app



    Problem: The middleware works correctly for async routes but does not work for sync routes.

    Example where timeout works:

    import asyncio
    from fastapi import APIRouter

    aparat_router = APIRouter()

    @aparat_router.api_route("/video", methods=["GET", "POST"])
    async def aparat_messages():
    await asyncio.sleep(5) # This correctly triggers the timeout
    return {"message": "Delayed Response"}



    Example where timeout does NOT work:

    import time
    from fastapi import APIRouter

    aparat_router = APIRouter()

    @aparat_router.api_route("/video", methods=["GET", "POST"])
    def aparat_messages():
    time.sleep(5) # This does NOT trigger the timeout
    return {"message": "Delayed Response"}



    Expected Behavior: Both sync and async routes should respect the timeout and return a 408 Request Timeout if execution exceeds the limit. Actual Behavior: The timeout only works for async routes. Sync routes block the event loop and do not trigger the timeout. Question: How can I ensure that my global timeout middleware also works for synchronous routes? Is there a better approach to handling request timeouts in FastAPI that supports both sync and async routes?

    fastapi==0.104.0
    uvicorn==0.23.0

    Continue reading...

Compartilhe esta Página