Middleware
Middleware components and request processing for the FastAPI Boilerplate.
CORS Middleware
Cross-Origin Resource Sharing
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # In production, replace with specific origins
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Authentication Middleware
JWT Authentication
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from datetime import datetime, timedelta
from typing import Optional
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
email: str = payload.get("sub")
if email is None:
raise credentials_exception
except JWTError:
raise credentials_exception
return email
Logging Middleware
Request Logging
from fastapi import FastAPI, Request
from fastapi.middleware.base import BaseHTTPMiddleware
import time
import logging
logger = logging.getLogger(__name__)
class LoggingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
logger.info(
f"{request.method} {request.url.path} "
f"status_code={response.status_code} "
f"process_time={process_time:.4f}s"
)
return response
app = FastAPI()
app.add_middleware(LoggingMiddleware)
Error Handling Middleware
Global Exception Handler
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
import logging
logger = logging.getLogger(__name__)
app = FastAPI()
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
logger.error(f"HTTP Exception: {exc.detail}")
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail},
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
logger.error(f"Validation Error: {exc.errors()}")
return JSONResponse(
status_code=422,
content={"detail": exc.errors()},
)
@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception):
logger.error(f"Unexpected Error: {str(exc)}")
return JSONResponse(
status_code=500,
content={"detail": "Internal Server Error"},
)
Rate Limiting Middleware
Request Rate Limiting
from fastapi import FastAPI, Request
from fastapi.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
import time
from collections import defaultdict
class RateLimitMiddleware(BaseHTTPMiddleware):
def __init__(self, app: FastAPI, limit: int = 100, window: int = 60):
super().__init__(app)
self.limit = limit
self.window = window
self.requests = defaultdict(list)
async def dispatch(self, request: Request, call_next):
client_ip = request.client.host
current_time = time.time()
# Clean up old requests
self.requests[client_ip] = [
t for t in self.requests[client_ip]
if current_time - t < self.window
]
# Check rate limit
if len(self.requests[client_ip]) >= self.limit:
return JSONResponse(
status_code=429,
content={"detail": "Too many requests"},
)
# Add current request
self.requests[client_ip].append(current_time)
return await call_next(request)
app = FastAPI()
app.add_middleware(RateLimitMiddleware, limit=100, window=60)