Open In App

Middlewares in FastAPI

Last Updated : 22 Aug, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

When you build an API with FastAPI, every request from client first passes through a pipeline before reaching your actual endpoint (function that handles the request). This is where middleware comes in.

A middleware is a piece of code that runs before the request reaches your endpoint and again after response is sent back. It:

  • Inspect or modify the incoming request.
  • Add extra processing like logging, authentication and compression.
  • Adjust or monitor outgoing response.
_middleware_in_fastapi_
Representation of Middleware

Middleware has two jobs:

  • Run some logic before request reaches the endpoint.
  • Run some logic after response leaves the endpoint.

Why Use Middleware?

Middleware lets you apply functionality automatically to every request and response, avoiding repetitive code in routes. This keeps your app cleaner, easier to maintain and more consistent.

Adding Middleware in FastAPI

Below is the syntax to add middleware in FastAPI:

app.add_middleware(MiddlewareClass, **options)

Parameters:

  • MiddlewareClass: middleware you want to use (like CORSMiddleware).
  • **options: Settings for that middleware (like allow_origins, minimum_size, etc.).

You just need to call app.add_middleware() before defining the routes.

Middlewares can be categorixed into two types

  1. Built-in Middlewares
  2. Custom or User-defined Middlewares

Built-in Middlewares in FastAPI

FastAPI (through Starlette) provides several built-in middlewares you can add directly. Let’s look at them one by one with examples.

1. CORSMiddleware (Cross-Origin Resource Sharing)

When frontend (React, Angular, Vue) and FastAPI backend run on different domains or ports (e.g., localhost:3000 and localhost:8000), browsers block these cross-origin requests for security. CORS Middleware solves this by allowing specific domains to access the API, enabling smooth frontend-backend communication.

Example: Let’s see how to enable CORS in FastAPI so that frontend can communicate with backend without being blocked.

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

# Create FastAPI app
app = FastAPI()

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"], 
    allow_credentials=True,
    allow_methods=["*"], 
    allow_headers=["*"], 
)

# Define a route
@app.get("/")
def home():
    return {"message": "CORS enabled!"}

Output

When you visit http://127.0.0.1:8000/ in your browser you will see:

CORSmiddleware_Output
CORS Middleware Output

Now, any frontend app can also access this API without being blocked.

Explanation:

  • allow_origins=["*"] allows all domains to access your API, allow_credentials=True allows cookies and authentication headers.
  • allow_methods=["*"] allows all HTTP methods (GET, POST, PUT, DELETE, etc.), allow_headers=["*"] allows all headers in requests.
  • @app.get("/"): Defines a simple GET route at /.
  • def home(): Returns a JSON response to confirm that CORS is enabled.

2. GZipMiddleware (Response Compression)

When your API needs to send large responses (for example, big JSON datasets) data can take longer to transfer and consume more bandwidth. GZipMiddleware automatically compresses these responses before sending them to the client, making them smaller, faster and more efficient.

Example: This example shows how to use GZipMiddleware to compress large responses automatically, saving bandwidth.

Python
from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware
app = FastAPI()

# Adding GZip middleware
app.add_middleware(GZipMiddleware, minimum_size=1000)

@app.get("/large-data")
def get_data():
    return {"data": "x" * 2000}  # A large response

Output

When you open /large-data, server compresses the response before sending it. The browser automatically decompresses it and shows:

GZipMiddleware_Output
GZipMiddleware Output

Explanation:

  • minimum_size=1000: Only responses larger than 1000 bytes will be compressed (to avoid unnecessary overhead on small responses).
  • @app.get("/large-data"): Defines an API endpoint /large-data.
  • return {"data": "x" * 2000}: Returns a large JSON response (~2000 characters). Since it’s bigger than 1000 bytes, it will be compressed automatically before sending to the client.

3. TrustedHostMiddleware (Restrict Allowed Hosts)

When deployed, FastAPI app may be accessed from many domains or IPs and allowing all hosts is risky. TrustedHostMiddleware fixes this by permitting requests only from trusted hostnames, blocking all others for added security. This helps protect against HTTP Host Header attacks by only allowing requests from a defined list of trusted hosts.

Example: In this example, we use TrustedHostMiddleware to restrict which hostnames can access the FastAPI app.

Python
from fastapi import FastAPI
from fastapi.middleware.trustedhost import TrustedHostMiddleware
app = FastAPI()

# Allow only these hosts
app.add_middleware(TrustedHostMiddleware, allowed_hosts=["example.com", "localhost"])

@app.get("/")
def home():
    return {"message": "Only trusted hosts can access this!"}

Output:

If you open using http://127.0.0.1:8000/, you get Invalid Host header (because 127.0.0.1 is not in the allowed_hosts).

TrustedHostMiddleware_output
TrsutedHostMiddleware Output

The Invalid Host Header error is expected and proves that TrustedHostMiddleware is working correctly. If you also want to allow 127.0.0.1, just add it to the list like this:

allowed_hosts=["example.com", "localhost", "127.0.0.1"]

Explanation:

  • app.add_middleware(): Adds TrustedHostMiddleware to the app. Only requests from example.com or localhost will be allowed and any request from a different host will be rejected.
  • @app.get("/"): Defines a simple route at the root /.
  • def home(): Returns a JSON response if the request comes from an allowed host.

4. HTTPSRedirectMiddleware (Force HTTPS)

When app is deployed, users might access it using plain HTTP, which is not secure. HTTPSRedirectMiddleware solves this by automatically redirecting all HTTP requests to HTTPS, ensuring that all communication between client and server is encrypted and safe. This is especially important in production environments where protecting sensitive data is critical.

Example: This example shows how to use HTTPSRedirectMiddleware to automatically redirect all HTTP requests to HTTPS for better security.

Python
from fastapi import FastAPI
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
app = FastAPI()

# Redirect HTTP -> HTTPS
app.add_middleware(HTTPSRedirectMiddleware)

@app.get("/")
def home():
    return {"message": "You are redirected to HTTPS!"}

Output

When you run this code locally, you’ll see warnings like:

WARNING: Invalid HTTP request received.

This happens because your local server is only running on HTTP and doesn’t have HTTPS configured. That’s normal nothing is wrong.

In a real production setup (with HTTPS enabled), this middleware automatically redirects all incoming HTTP requests to HTTPS, so users always connect securely. For example:

http://example.com -> redirects to -> https://example.com

And then you’ll see the response:

{"message": "You are redirected to HTTPS!"}

Explanation:

  • app.add_middleware(HTTPSRedirectMiddleware): Adds middleware so that any incoming HTTP request is automatically redirected to HTTPS.
  • @app.get("/"): Defines a simple GET endpoint at the root URL (/).
  • def home(): Returns a JSON response after the redirection happens.

Middleware vs Dependencies in FastAPI

When building a FastAPI application, you may wonder whether to use middleware or dependencies for certain logic. The choice depends on the scope of what you want to apply:

Use Middleware when logic should run for every request and response globally, regardless of which route is called.

Examples:

  • Enabling CORS so any frontend can communicate with the backend.
  • Redirecting all HTTP traffic to HTTPS.
  • Compressing large responses to save bandwidth.

Use Dependencies when logic is needed only for specific routes or endpoints, not whole application.

Examples:

  • Checking authentication or user roles only on protected endpoints.
  • Validating query parameters for a single route.
  • Applying business logic that differs between APIs.

Best Practices

  • Use built-in middleware for common tasks instead of writing your own from scratch.
  • Add only what you really need too many middlewares can slow down performance.
  • Configure options carefully (e.g., don’t use allow_origins=["*"] in production).
  • Always add security-related middleware (like HTTPS redirect) when deploying.

Related Articles:


Article Tags :

Explore