FastAPI Middleware

Middleware is a function that executes before and after every request reaches the route handler.

Middleware can be used for common logic such as adding logs, modifying requests/responses, handling CORS, etc.


How middleware works

Middleware execution flow:

  • Request reaches middleware
  • Middleware executes preprocessing logic
  • Middleware passes the request to the next middleware or route function.
  • Route function returns response
  • Middleware executes post-processing logic
  • Response returned to client

Name Function
Client Browsers, frontend apps, Postman, etc. send HTTP requests to FastAPI
Request HTTP request object, containing data such as URL, Header, Body, Cookie
Middleware 1 The first layer of processing after a request enters
Middleware 2 Second layer processing logic
Middleware N Multiple middleware execute in order
Route handler function (Path Operation) The place where business code is actually executed
Response phase After the route returns a Response, the response passes through the middleware again.
Middleware returns in reverse order Responses return in "reverse order"
Response response The data ultimately returned to the client

Create middleware

Usage@app.middleware("http")Creating middleware with decorators:

Example

import time
from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    # 1. Pre-request processing: record start time
    start_time = time.time()

    # 2. Pass the request to the next middleware or route function
    response = await call_next(request)

    # 3. Post-response processing: calculate processing time and add response headers.
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response


@app.get("/")
async def root():
    return {"message": "Hello World"}

Code explanation:

PartDescription
@app.middleware("http")Declare this as an HTTP middleware.
request: RequestCurrent request object
call_nextCallback to invoke the next middleware or route function.
await call_next(request)Pass the request to the next layer and get the response

call_nextReceiverequestParameters and returnresponse. You can callcall_nextModify the request before the call, and modify the response after the call.


Request logging middleware

The following middleware logs basic information about each request:

Example

import time
import logging
from fastapi import FastAPI, Request

app = FastAPI()

logger = logging.getLogger("uvicorn.access")


@app.middleware("http")
async def log_requests(request: Request, call_next):
    # Record request information
    logger.info(fRequest: {request.method} {request.url})

    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time

    # Record response information
    logger.info(
        f"Response: {request.method} {request.url} "
        fStatus code={response.status_code} elapsed time={process_time:.3f}s
    )

    return response

Middleware execution order

Middleware executes in registration order; requests pass through middleware in forward order, and responses pass through in reverse order:

请求 -> 中间件A(前) -> 中间件B(前) -> 路由函数
响应 <- 中间件A(后) <- 中间件B(后) <- 路由函数

Middleware registration order is important. If you have two middleware A and B, and register A first, the request passes through A first, then B, but the response passes through B first, then A.


Using Starlette's built-in middleware

FastAPI inherits from Starlette, so middleware provided by Starlette can be used directly:

Example

from fastapi import FastAPI
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware

app = FastAPI()

# Force HTTPS redirect
app.add_middleware(HTTPSRedirectMiddleware)


@app.get("/")
async def root():
    return {"message": Access using HTTPS}

Common built-in middleware:

middlewareDescription
HTTPSRedirectMiddlewareForce redirect HTTP requests to HTTPS
TrustedHostMiddlewareRestrict allowed hostnames
GZipMiddlewareAutomatically compress response content
CORSMiddlewareHandle cross-origin requests (detailed in the next chapter)

GZip compression middleware

Enabling GZip compression can reduce response size and improve transfer speed:

Example

from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware

app = FastAPI()

# Automatically compress when the response size exceeds 1000 bytes
app.add_middleware(GZipMiddleware, minimum_size=1000)


@app.get("/")
async def root():
    return {"message": "This response may be GZip compressed"}

Summary

  • Middleware executes common logic in the request/response processing chain.
  • Usage@app.middleware("http")Creating custom middleware
  • call_next(request)Pass the request to the next layer
  • Middleware executes in registration order (requests in forward order, responses in reverse order)
  • FastAPI/Starlette provides built-in middleware such as CORS, GZip, HTTPS redirect, etc.
other extensions