-
Notifications
You must be signed in to change notification settings - Fork 102
Open
Description
Summary
When applying @limiter.limit to a FastAPI route that uses from __future__ import annotations and Annotated[..., Depends(...)],
the decorator breaks dependency resolution if the endpoint does not
explicitly declare a request: Request parameter. The route either
fails at import time (“No request or websocket argument”) or returns
422 responses because FastAPI sees an altered signature.
Minimal reproduction
from __future__ import annotations
from typing import Annotated
from fastapi import Depends, FastAPI
from slowapi import Limiter
from slowapi.util import get_remote_address
from starlette.requests import Request
app = FastAPI()
limiter = Limiter(key_func=get_remote_address)
async def dep(request: Request) -> str:
return "ok"
@app.get("/demo")
@limiter.limit("5/minute")
async def demo_endpoint(value: Annotated[str, Depends(dep)]) -> str:
return valueSteps:
- Run the app with FastAPI/uvicorn (FastAPI 0.119.1, SlowAPI 0.1.9,
Python 3.12). - Observe either:
- Import-time error: Exception: No "request" or "websocket"
argument on function "<function demo_endpoint ...>" - Or 422 responses when calling /demo because FastAPI cannot
resolve dependencies.
- Import-time error: Exception: No "request" or "websocket"
Expected
- The decorator should work with FastAPI’s annotation styles (from
future import annotations, Annotated[Depends(...)]) even when
the endpoint doesn’t declare request explicitly. - Requests should succeed until the limit is exceeded, then return
429 with rate-limit headers.
Actual
- Import-time crash (“No request or websocket argument”) or 422
responses due to a mutated signature that FastAPI can’t resolve.
Environment
- Python: 3.12
- FastAPI: 0.119.1
- SlowAPI: 0.1.9 (PyPI)
- OS: macOS / Linux (reproducible in both)
Notes / possible fix direction
- The decorator currently wraps the endpoint and requires a request
param, altering the signature FastAPI inspects. - Preserving the original callable’s signature (or rebuilding
it correctly) and setting wrapped, signature,
annotations, and globals appears necessary for FastAPI’s
dependency resolver. - Avoiding the decorator wrapper and registering limits directly
(using LimitGroup + limiter._route_limits) works around the issue,
but an upstream fix would let users keep the decorator.
Workaround
- Register limits manually and enforce via a dependency that calls
_check_request_limit + _inject_headers, keeping the endpoint
signature untouched.
Metadata
Metadata
Assignees
Labels
No labels