Middleware runs for every request to handle common tasks like logging or security. It works globally so you don't repeat code in each route.
Why middleware processes requests globally in FastAPI
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
FastAPI
from fastapi import FastAPI from starlette.middleware.base import BaseHTTPMiddleware app = FastAPI() class CustomMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): # Code before request response = await call_next(request) # Code after request return response app.add_middleware(CustomMiddleware)
Middleware classes must implement a dispatch method.
The call_next function calls the next step in the request chain.
Examples
FastAPI
from fastapi import FastAPI from starlette.middleware.base import BaseHTTPMiddleware app = FastAPI() class LogMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): print(f"Request path: {request.url.path}") response = await call_next(request) return response app.add_middleware(LogMiddleware)
FastAPI
from fastapi import FastAPI from starlette.middleware.base import BaseHTTPMiddleware app = FastAPI() class AddHeaderMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): response = await call_next(request) response.headers["X-Custom-Header"] = "MyValue" return response app.add_middleware(AddHeaderMiddleware)
Sample Program
This example adds middleware that measures and prints how long each request takes. It runs for every request globally.
FastAPI
from fastapi import FastAPI from starlette.middleware.base import BaseHTTPMiddleware from starlette.requests import Request from starlette.responses import Response app = FastAPI() class TimerMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): import time start = time.time() response: Response = await call_next(request) duration = time.time() - start print(f"Request took {duration:.4f} seconds") return response app.add_middleware(TimerMiddleware) @app.get("/") async def root(): return {"message": "Hello World"}
Important Notes
Middleware runs before and after every request automatically.
Use middleware for tasks that apply to all routes to avoid repeating code.
Middleware order matters: it runs in the order added.
Summary
Middleware processes requests globally to handle shared tasks.
This avoids repeating code in each route handler.
Middleware runs before and after every request automatically.
Practice
1. Why does FastAPI middleware process requests globally across all routes?
easy
Solution
Step 1: Understand middleware purpose
Middleware is designed to run code before and after every request to handle common tasks.Step 2: Recognize global effect
It applies globally to avoid repeating the same code in each route handler.Final Answer:
To handle shared tasks like logging or authentication once for all requests -> Option BQuick Check:
Middleware = shared tasks globally [OK]
Hint: Middleware runs for all requests to avoid code repetition [OK]
Common Mistakes:
- Thinking middleware runs only on selected routes
- Believing middleware replaces route handlers
- Assuming middleware slows down app intentionally
2. Which of the following is the correct way to add middleware globally in FastAPI?
easy
Solution
Step 1: Recall FastAPI middleware syntax
FastAPI uses the methodadd_middleware()on the app instance to add middleware globally.Step 2: Eliminate incorrect options
Options A, B and C are invalid: A instantiates middleware without adding it to the app, B and C are invalid method calls.Final Answer:
app.add_middleware(SomeMiddleware) -> Option AQuick Check:
Use add_middleware() to add middleware globally [OK]
Hint: Use app.add_middleware() to add middleware globally [OK]
Common Mistakes:
- Using app.middleware() which does not exist
- Trying to add middleware on route instead of app
- Instantiating middleware without adding it to app
3. Given this middleware code in FastAPI:
What will be printed when a client requests
from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware
class PrintMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
print("Before request")
response = await call_next(request)
print("After request")
return response
app = FastAPI()
app.add_middleware(PrintMiddleware)
@app.get("/hello")
async def hello():
return {"message": "Hello"}What will be printed when a client requests
/hello?medium
Solution
Step 1: Understand middleware dispatch flow
The middleware prints "Before request" before calling the next handler, then "After request" after the response is received.Step 2: Trace the request lifecycle
When /hello is requested, the middleware prints "Before request", then the route runs, then prints "After request".Final Answer:
Before request After request -> Option AQuick Check:
Middleware prints before and after request [OK]
Hint: Middleware prints before and after call_next() [OK]
Common Mistakes:
- Assuming prints happen in reverse order
- Thinking only one print runs
- Believing middleware does not print anything
4. You wrote this middleware but it does not run for any requests:
What is the likely problem?
class MyMiddleware:
async def dispatch(self, request, call_next):
print("Middleware active")
response = await call_next(request)
return response
app = FastAPI()
app.add_middleware(MyMiddleware)What is the likely problem?
medium
Solution
Step 1: Check middleware class inheritance
FastAPI middleware classes must inherit fromBaseHTTPMiddlewareor implement ASGI interface properly.Step 2: Identify missing inheritance
MyMiddleware lacks inheritance, so FastAPI cannot use it as middleware.Final Answer:
MyMiddleware does not inherit from BaseHTTPMiddleware -> Option CQuick Check:
Middleware must inherit BaseHTTPMiddleware [OK]
Hint: Middleware class must inherit BaseHTTPMiddleware [OK]
Common Mistakes:
- Making dispatch synchronous instead of async
- Adding middleware before routes (order usually doesn't block)
- Thinking @middleware decorator is required for class middleware
5. You want to add middleware that logs request time but only for routes under
/api. Why does FastAPI middleware still run on all routes, and how can you limit it?hard
Solution
Step 1: Understand middleware scope
FastAPI middleware always runs globally on every request to handle shared tasks.Step 2: Limit middleware effect by path check
To restrict middleware to /api routes, check the request URL path inside middleware and skip processing for others.Final Answer:
Middleware runs globally by design; to limit, check path inside middleware and skip non-/api requests -> Option DQuick Check:
Middleware global; filter inside middleware [OK]
Hint: Middleware always global; filter requests inside middleware [OK]
Common Mistakes:
- Expecting middleware to attach only to some routes automatically
- Trying to pass routes to add_middleware (not supported)
- Thinking middleware can be disabled per route with decorators
