[Python] TypeError in FastAPI when using APIRoute with a Router

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

  1. Stack

    Stack Membro Participativo

    I have a FastAPI backend and i'm trying to implement an APIRoute class to handle logic before and after the request (logging).

    # app.py
    from fastapi import FastAPI, APIRouter

    from backend.app.routers import questions


    API_VERSION = "v1"

    app = FastAPI(lifespan=lifespan)
    api_v1_router = APIRouter(prefix=f"/{API_VERSION}")
    api_v1_router.include_router(questions.router)
    app.include_router(api_v1_router)

    if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=80)


    # questions.py
    from typing import Callable
    from fastapi import APIRouter, Request, Response

    class LoggingAPIRoute(APIRoute):
    @staticmethod
    async def access_log_req(request: Request) -> None:
    print("request...")

    @staticmethod
    async def access_log_res(request: Request, response: Response) -> None:
    print("response...")

    async def get_route_handler(self) -> Callable:
    original_route_handler = super().get_route_handler()

    async def custom_route_handler(request: Request) -> Response:
    await self.access_log_req(request=request)
    try:
    response = await original_route_handler(request)
    await self.access_log_res(request=request, response=response)
    return response
    except Exception as e:
    return "oh snap!"

    return custom_route_handler


    router = APIRouter(route_class=LoggingAPIRoute)

    @router.post("/retrieve", response_class=JSONResponse)
    async def retrieve(request: Request, auth_result: str = Security(auth.verify)):
    pass



    Calling the v1/retrieve with curl causes an exception to be thrown: TypeError: the first argument must be callable. When removing LoggingAPIRoute usage from the router, the problem is solved.

    Any ideas?

    curl localhost:80/v1/retrieve -X POST

    INFO: 127.0.0.1:52860 - "POST /v1/retrieve HTTP/1.1" 500 Internal Server Error
    ERROR: Exception in ASGI application
    Traceback (most recent call last):
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/uvicorn/protocols/http/h11_impl.py", line 403, in run_asgi
    result = await app( # type: ignore[func-returns-value]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    self.scope, self.receive, self.send
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
    return await self.app(scope, receive, send)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/fastapi/applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/middleware/errors.py", line 187, in __call__
    raise exc
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/middleware/errors.py", line 165, in __call__
    await self.app(scope, receive, _send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/middleware/cors.py", line 85, in __call__
    await self.app(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    raise exc
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/routing.py", line 714, in __call__
    await self.middleware_stack(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/routing.py", line 734, in app
    await route.handle(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/routing.py", line 288, in handle
    await self.app(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/routing.py", line 76, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    raise exc
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/routing.py", line 73, in app
    response = await f(request)
    ^^^^^^^^^^^^^^^^
    File "/Users/boss/foo/.venv/lib/python3.13/site-packages/starlette/concurrency.py", line 36, in run_in_threadpool
    func = functools.partial(func, *args, **kwargs)
    TypeError: the first argument must be callable

    Continue reading...

Compartilhe esta Página