FastAPI Middleware Integration
Relevant source files
The following files were used as context for generating this wiki page:
The FastAPI Middleware Integration in FastLimit provides a seamless way to enforce rate limits and communicate limit status to clients via industry-standard HTTP headers. It consists of two primary components: a specialized middleware for header injection and a decorator-based mechanism that interacts with the request state to pass rate limiting metadata across the application stack.
This integration ensures that clients receive critical feedback, such as the maximum allowed requests (X-RateLimit-Limit), remaining capacity (X-RateLimit-Remaining), and the time until reset (X-RateLimit-Reset). In the event of a limit violation, it automatically handles the generation of 429 Too Many Requests responses with appropriate Retry-After instructions.
Architecture and Data Flow
The integration operates through a cooperative model between the limiter.limit decorator and the RateLimitHeadersMiddleware. The decorator performs the actual rate limit check against the Redis backend and stores the resulting metadata in the FastAPI request.state. The middleware then intercepts the response to inject these values as HTTP headers.
Request Processing Flow
The following diagram illustrates how a request traverses the rate limiting layers:
Core Components
RateLimitHeadersMiddleware
This class inherits from BaseHTTPMiddleware and is responsible for the final injection of headers into the starlette.responses.Response object. It serves as the standard way to provide observability to clients regarding their current usage.
| Feature | Description |
|---|---|
| Header Injection | Automatically adds X-RateLimit headers to all responses if info is available. |
| Error Handling | Catches RateLimitExceeded exceptions and converts them into standardized JSON 429 responses. |
| State Tracking | Reads from request.state.rate_limit_info which is populated by decorators. |
| Industry Standards | Follows header patterns used by GitHub, Twitter, and Stripe. |
Sources: fastlimit/middleware.py:22-54, README.md:144-152
Decorator Interaction
The create_limit_decorator (accessed via @limiter.limit) does more than just blocking requests. It uses check_with_info() to retrieve the full state of the rate limit from Redis in a single atomic operation and stores it in the request state.
# From fastlimit/decorators.py:192-200
result = await limiter.check_with_info(
key=key,
rate=rate,
algorithm=algorithm,
tenant_type=tenant_type,
cost=cost,
)
# Store usage info for middleware headers
if hasattr(request, "state"):
request.state.rate_limit_info = {
"limit": result.limit,
"remaining": result.remaining,
"window_seconds": result.window_seconds,
"ttl": result.retry_after if result.retry_after > 0 else result.window_seconds,
}
Sources: fastlimit/decorators.py:186-215
Standard Headers Reference
FastLimit implements a set of de facto standard headers to ensure compatibility with common API clients and load balancers.
| Header | Type | Description |
|---|---|---|
X-RateLimit-Limit | String | The maximum number of requests allowed in the current window. |
X-RateLimit-Remaining | Integer | The number of requests remaining in the current time window. |
X-RateLimit-Reset | Timestamp | Unix timestamp indicating when the current window resets. |
Retry-After | Integer | (429 Only) Seconds to wait before the next request is allowed. |
Sources: fastlimit/middleware.py:28-35, tests/test_middleware.py:53-64
Implementation Examples
Basic Integration
To enable the full suite of features, the middleware must be added to the FastAPI app instance, and endpoints must be decorated.
from fastapi import FastAPI
from fastlimit import RateLimiter, RateLimitHeadersMiddleware
app = FastAPI()
limiter = RateLimiter(redis_url="redis://localhost:6379")
# Register the middleware
app.add_middleware(RateLimitHeadersMiddleware)
@app.get("/api/data")
@limiter.limit("100/minute")
async def get_data(request: Request):
return {"data": "success"}
Sources: examples/fastapi_app.py:44-48, fastlimit/middleware.py:40-54
Handling Limit Violations
While the middleware provides a default 429 handler, developers can implement a custom global exception handler to modify the error payload while preserving the required headers.
@app.exception_handler(RateLimitExceeded)
async def rate_limit_handler(request: Request, exc: RateLimitExceeded):
return JSONResponse(
status_code=429,
content={
"error": "Rate limit exceeded",
"message": str(exc),
"retry_after": exc.retry_after,
},
headers={
"X-RateLimit-Limit": exc.limit,
"X-RateLimit-Remaining": str(exc.remaining),
"X-RateLimit-Reset": str(exc.retry_after),
"Retry-After": str(exc.retry_after),
},
)
Sources: examples/fastapi_app.py:72-87
Security and Proxy Considerations
The middleware and decorators include logic to identify the client's identity (the "key"). By default, this is the client's IP address. For production environments behind a reverse proxy (like Nginx or Cloudflare), the system can be configured to trust specific headers.
trust_proxy_headers: When set toTrue, the system checksX-Forwarded-ForandX-Real-IP.- Default Behavior: If not explicitly enabled, proxy headers are ignored to prevent IP spoofing attacks where a client could bypass limits by providing a fake
X-Forwarded-Forheader.
Sources: fastlimit/decorators.py:228-265, fastlimit/decorators.py:302-307
The FastAPI Middleware Integration in FastLimit provides a robust, production-ready solution for managing API traffic. By combining decorator-level enforcement with middleware-level reporting, it ensures that both the server and the client have clear, real-time information regarding rate limit status and enforcement actions.