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
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:
| Part | Description |
|---|---|
@app.middleware("http") | Declare this as an HTTP middleware. |
request: Request | Current request object |
call_next | Callback 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 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 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:
| middleware | Description |
|---|---|
HTTPSRedirectMiddleware | Force redirect HTTP requests to HTTPS |
TrustedHostMiddleware | Restrict allowed hostnames |
GZipMiddleware | Automatically compress response content |
CORSMiddleware | Handle 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.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.