Skip to main content

Global Middleware and Dependencies

When you need to enforce authentication, inject database sessions, or add custom headers to every request in your API, you can configure global logic directly on the FastAPI class.

Apply Global Dependencies

To run logic before every path operation in your application, use the dependencies parameter when instantiating the FastAPI class. This is useful for security requirements like API key validation or token verification.

from fastapi import Depends, FastAPI, Header, HTTPException

async def verify_token(x_token: str = Header()):
if x_token != "fake-super-secret-token":
raise HTTPException(status_code=400, detail="X-Token header invalid")

async def verify_key(x_key: str = Header()):
if x_key != "fake-super-secret-key":
raise HTTPException(status_code=400, detail="X-Key header invalid")
return x_key

# These dependencies apply to every route in the app
app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])

@app.get("/items/")
async def read_items():
return [{"item": "Portal Gun"}]

Global dependencies defined in fastapi.applications.FastAPI are executed for every request, including those in sub-routers included via app.include_router().

Create Custom HTTP Middleware

For logic that needs to wrap the entire request/response cycle—such as timing requests or logging—use the @app.middleware("http") decorator. This allows you to execute code before the request reaches a path operation and after the response is generated.

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()

# The request is processed by the path operation
response = await call_next(request)

# Logic executed after the path operation finishes
process_time = time.perf_counter() - start_time
response.headers["X-Process-Time"] = str(process_time)

return response

The call_next function receives the request and returns the response generated by the rest of the application.

Configure CORS and Standard Middleware

FastAPI provides specialized middleware classes for common tasks like Cross-Origin Resource Sharing (CORS). Use the app.add_middleware() method to register these classes.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
"http://localhost.tiangolo.com",
"https://localhost.tiangolo.com",
"http://localhost:8080",
]

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

Other standard middlewares available in FastAPI include:

  • fastapi.middleware.gzip.GZipMiddleware: Compresses responses for clients that support it.
  • fastapi.middleware.trustedhost.TrustedHostMiddleware: Enforces that all incoming requests have a correct Host header to prevent HTTP Host Header attacks.

Define Global Exception Handlers

You can override how FastAPI handles specific exceptions globally using the @app.exception_handler() decorator. This is often used to return custom JSON structures when a specific error occurs anywhere in the app.

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

class UnicornException(Exception):
def __init__(self, name: str):
self.name = name

app = FastAPI()

@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):
return JSONResponse(
status_code=418,
content={"message": f"Oops! {exc.name} did something."},
)

FastAPI also allows you to override default handlers for HTTPException and RequestValidationError by using those classes as the argument to the decorator.

Troubleshooting

Middleware Execution Order

The order in which you add middleware matters. In FastAPI, the middleware stack is built such that the last middleware added is the outermost layer. This means the last middleware added with app.add_middleware() or @app.middleware() will be the first to receive a request and the last to process a response.

Dependency Return Values

Unlike dependencies used directly in path operation functions, global dependencies defined in the FastAPI constructor do not return their values to the route handlers. They are intended for side effects (like validation or logging) rather than data injection. If you need the return value of a dependency inside your function, you must also include it in the function signature using Depends().

Background Tasks and Middleware

If you use BackgroundTasks in your routes, be aware that custom middleware wrapping the response might finish executing before the background task completes. Middleware logic that depends on the final state of the response should be tested carefully when background tasks are involved.