How to Use Middleware in FastAPI: Simple Guide with Examples
In FastAPI, you use
Middleware by creating a middleware class or function and adding it with app.add_middleware(). Middleware runs code before and after each request, letting you modify requests or responses globally.Syntax
To use middleware in FastAPI, you import Middleware and a middleware class like BaseHTTPMiddleware from starlette.middleware.base. Then you create a middleware class with a dispatch method that handles requests and responses. Finally, add it to your FastAPI app using app.add_middleware().
This lets you run code before the request reaches your route and after the response is created.
python
from fastapi import FastAPI, Request from starlette.middleware.base import BaseHTTPMiddleware class SimpleMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): # Code before request response = await call_next(request) # Code after response return response app = FastAPI() app.add_middleware(SimpleMiddleware)
Example
This example shows a middleware that logs the request method and URL before processing, and adds a custom header to the response.
python
from fastapi import FastAPI, Request from starlette.middleware.base import BaseHTTPMiddleware class LoggingMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): print(f"Request: {request.method} {request.url}") response = await call_next(request) response.headers["X-Custom-Header"] = "Middleware was here" return response app = FastAPI() app.add_middleware(LoggingMiddleware) @app.get("/") async def root(): return {"message": "Hello from FastAPI with middleware!"}
Output
Request: GET http://127.0.0.1:8000/
Response headers include: X-Custom-Header: Middleware was here
Common Pitfalls
- Not calling
await call_next(request)insidedispatchwill block the request and cause timeouts. - Modifying the request object directly is not recommended; instead, use headers or context.
- Middleware order matters: the first added runs first on request and last on response.
- Using synchronous code inside
dispatchcan block the server; always use async.
python
from fastapi import FastAPI, Request, Response from starlette.middleware.base import BaseHTTPMiddleware class WrongMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): # Missing await call_next(request) blocks the request print("This will block the request") return Response("Blocked", status_code=403) app = FastAPI() app.add_middleware(WrongMiddleware) # This middleware will block all requests # Correct way: class RightMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): response = await call_next(request) return response
Quick Reference
FastAPI Middleware Quick Tips:
- Use
BaseHTTPMiddlewareto create middleware classes. - Always
await call_next(request)to continue processing. - Middleware runs in the order added: first added runs first on request, last on response.
- Use middleware for logging, headers, authentication, or modifying responses globally.
Key Takeaways
Add middleware in FastAPI using app.add_middleware() with a class inheriting BaseHTTPMiddleware.
Always await call_next(request) inside dispatch to pass control to the next handler.
Middleware runs code before and after each request, useful for logging, headers, or auth.
Avoid blocking code and modifying requests directly inside middleware.
Middleware order affects execution sequence on requests and responses.