Master FastAPI Middleware: From Built‑in to Custom Auth and Logging
This guide explains how FastAPI middleware works, outlines its request‑response lifecycle, shows built‑in examples like CORS and HTTPS redirect, and demonstrates how to create custom middleware for logging, authentication, and other cross‑cutting concerns.
Middleware is a function that runs before each request is handled by a specific path operation and also runs before each response is returned.
It receives every request sent to the application.
It can operate on the request or run necessary code.
It then passes the request to the rest of the application (handled by a path operation).
It receives the response generated by the application.
It can operate on the response or run necessary code.
Finally, it returns the response.
Overall, middleware execution can be divided into the following stages:
1. Request phase: Middleware processes the request in the order it was added.
2. Routing: The request reaches the corresponding path operation function.
3. Response phase: Middleware processes the response in reverse order.
<code>Request → [Middleware1 → Middleware2 → Route Handler → Middleware2 → Middleware1] → Response</code>Middleware wraps the application, intercepting all incoming requests and outgoing responses. It executes in the order added (similar to the onion model: request from outer to inner, response from inner to outer).
Typical use cases include:
Global authentication (e.g., JWT verification)
Request logging
Adding custom response headers
Exception handling
Rate limiting or caching
Built‑in Middleware
FastAPI provides several built‑in middleware, such as the CORS middleware:
<code>from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # allowed origins
allow_methods=["*"], # allowed HTTP methods
allow_headers=["*"], # allowed request headers
)
</code>HTTPS redirect middleware:
<code>from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
app.add_middleware(HTTPSRedirectMiddleware) # force all requests to use HTTPS
</code>Creating Middleware
Beyond the built‑ins, you can define custom middleware by decorating a function with @app.middleware("http") .
A middleware function receives the following parameters:
request : the incoming request.
call_next : a function that forwards the request to the appropriate path operation.
The function returns the response generated by that path operation.
You can modify the response before returning it.
<code>import time
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.perf_counter()
response = await call_next(request)
process_time = time.perf_counter() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
</code>This adds a custom X-Process-Time header containing the time taken to process the request (in seconds).
Example of a custom authentication middleware:
<code>from fastapi import FastAPI, Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
class AuthMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
api_key = request.headers.get("X-API-KEY")
if api_key != "secret-key": # replace with your key validation logic
return Response("Unauthorized", status_code=401)
response = await call_next(request)
return response
app.add_middleware(AuthMiddleware)
@app.get("/secure-data")
async def secure_endpoint():
return {"message": "You accessed protected data!"}
</code>The middleware checks the X-API-KEY header.
If the key is missing or incorrect, it returns a 401 Unauthorized response.
Precautions
Avoid performing time‑consuming operations (e.g., synchronous blocking code) inside middleware.
Exceptions raised in middleware are returned directly to the client and are not caught by FastAPI’s exception handlers unless you handle them manually.
Middleware cannot directly use FastAPI’s dependency‑injection system.
Summary
By flexibly using middleware, you can add global functionality to a FastAPI application without repeating code in each route. For more details, refer to the official FastAPI documentation.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.