Skip to main content

Essential middlewares for FastAPI

Project description

FastAPI Middlewares

Essential middlewares for FastAPI applications.

CI PyPI DownloadsPyPI version Python Versions License: MIT

Features

  • 🔍 Request ID Tracking - Unique IDs for request tracing
  • ⏱️ Request Timing - Measure response times
  • 🔒 Security Headers - OWASP-compliant security headers
  • 📝 Structured Logging - JSON-formatted request/response logs
  • 🚨 Error Handling - Graceful error responses with tracebacks
  • Easy Setup - One-line configuration with sensible defaults

Installation

pip install fastapi-middlewares

Or with uv:

uv add fastapi-middlewares

Quick Start

from fastapi import FastAPI
from middlewares import add_essentials

app = FastAPI()

# Add all essential middlewares in one line
add_essentials(app)

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

That's it! Your app now has:

  • ✅ Request ID tracking
  • ✅ Request timing
  • ✅ Security headers
  • ✅ CORS support
  • ✅ Error handling
  • ✅ Logging
  • ✅ GZip compression

Middlewares

1. Request ID Middleware

Adds a unique ID to each request for tracing.

from fastapi import FastAPI, Request
from middlewares import RequestIDMiddleware

app = FastAPI()
app.add_middleware(RequestIDMiddleware)

@app.get("/users/{user_id}")
def get_user(user_id: int, request: Request):
    request_id = request.scope.get("request_id")
    return {"user_id": user_id, "request_id": request_id}

Response Headers:

X-Request-ID: 550e8400-e29b-41d4-a716-446655440000

Options:

  • header_name: Custom header name (default: "X-Request-ID")

2. Request Timing Middleware

Tracks how long each request takes.

from middlewares import RequestTimingMiddleware

app.add_middleware(RequestTimingMiddleware)

Response Headers:

X-Process-Time: 0.0245

Options:

  • header_name: Custom header name (default: "X-Process-Time")

3. Security Headers Middleware

Adds OWASP-recommended security headers to protect against common attacks.

from middlewares import SecurityHeadersMiddleware

app.add_middleware(SecurityHeadersMiddleware)

Default Headers:

  • Cache-Control: no-store, max-age=0 - Prevents caching of sensitive data
  • Content-Security-Policy: frame-ancestors 'none' - Prevents clickjacking
  • X-Content-Type-Options: nosniff - Prevents MIME-sniffing attacks
  • X-Frame-Options: DENY - Additional clickjacking protection
  • Referrer-Policy: no-referrer - Prevents URL leakage
  • Permissions-Policy: geolocation=(), microphone=(), camera=() - Disables unnecessary browser features
  • Strict-Transport-Security: max-age=31536000; includeSubDomains - HTTPS enforcement (added automatically for HTTPS connections)

The middleware also removes server identification headers (Server, X-Powered-By) to reduce information disclosure.

Custom Headers:

app.add_middleware(
    SecurityHeadersMiddleware,
    headers={
        "Cache-Control": "no-cache",
        "Content-Security-Policy": "default-src 'self'",
        "Custom-Header": "custom-value"
    },
    hsts_max_age=63072000  # 2 years
)

Options:

  • headers: Dict of custom security headers (overrides defaults)
  • hsts_max_age: HSTS max-age in seconds (default: 31536000 = 1 year)

Note: Default headers are compatible with FastAPI's Swagger UI and ReDoc. The middleware respects headers already set by your application routes.

4. Logging Middleware

Logs all requests and responses with structured output.

from middlewares import LoggingMiddleware

app.add_middleware(
    LoggingMiddleware,
    logger_name="my_app",
    skip_paths=["/health", "/metrics"]
)

Log Output:

{
  "request_id": "550e8400-...",
  "method": "GET",
  "path": "/users/123",
  "status_code": 200,
  "process_time": "0.0245s"
}

Options:

  • logger_name: Logger name (default: "fastapi_middlewares")
  • skip_paths: Paths to skip logging (default: ["/health", "/metrics"])

5. Error Handling Middleware

Catches exceptions and returns formatted JSON errors.

from middlewares import ErrorHandlingMiddleware

app.add_middleware(
    ErrorHandlingMiddleware,
    include_traceback=False  # Set True for development
)

Error Response:

{
  "error": "ValueError",
  "message": "Invalid user ID",
  "request_id": "550e8400-..."
}

Custom Error Handlers:

from starlette.responses import JSONResponse

async def handle_value_error(scope, exc):
    return JSONResponse(
        status_code=400,
        content={"error": "bad_request", "message": str(exc)}
    )

app.add_middleware(
    ErrorHandlingMiddleware,
    custom_handlers={ValueError: handle_value_error}
)

Options:

  • include_traceback: Include full traceback (default: False)
  • custom_handlers: Dict mapping exception types to handler functions

6. CORS Middleware

Wrapper around Starlette's CORSMiddleware.

from middlewares import add_cors

add_cors(
    app,
    allow_origins=["http://localhost:3000"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)

7. GZip Compression

Wrapper around Starlette's GZipMiddleware.

from middlewares import add_gzip

add_gzip(app, minimum_size=1000)

Middleware Ordering

Order matters! Middlewares execute in reverse order of addition.

Recommended Order:

from fastapi import FastAPI
from middlewares import (
    ErrorHandlingMiddleware,
    SecurityHeadersMiddleware,
    RequestIDMiddleware,
    RequestTimingMiddleware,
    LoggingMiddleware,
    add_cors,
    add_gzip,
)

app = FastAPI()

# Last added = First executed
add_gzip(app)                               # 7. Compress response
app.add_middleware(LoggingMiddleware)       # 6. Log request/response
app.add_middleware(RequestTimingMiddleware) # 5. Time request
app.add_middleware(RequestIDMiddleware)     # 4. Add request ID
app.add_middleware(SecurityHeadersMiddleware) # 3. Add security headers
add_cors(app)                               # 2. Handle CORS
app.add_middleware(ErrorHandlingMiddleware) # 1. Catch errors (outermost)

Why This Order?

  1. Error handling first - Catches all exceptions from other middlewares
  2. CORS early - Handles preflight requests before processing
  3. Security headers - Added to all responses
  4. Request ID - Available for all downstream middlewares and logging
  5. Timing - Measures full request duration
  6. Logging - Logs complete request/response cycle
  7. Compression last - Compresses the final response body

Complete Example

from fastapi import FastAPI, HTTPException
from middlewares import add_essentials

app = FastAPI(title="My API")

# Add all middlewares with custom config
add_essentials(
    app,
    cors_origins=["http://localhost:3000"],
    include_traceback=False,  # Set True for development
    logger_name="my_api"
)

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

@app.get("/users/{user_id}")
def get_user(user_id: int):
    if user_id < 1:
        raise ValueError("Invalid user ID")
    return {"user_id": user_id, "name": "John"}

@app.get("/error")
def error():
    raise HTTPException(status_code=404, detail="Not found")

Run it:

uvicorn main:app --reload

Test it:

# Check headers
curl -I http://localhost:8000/

# Expected headers:
# X-Request-ID: 550e8400-...
# X-Process-Time: 0.0245
# X-Content-Type-Options: nosniff
# X-Frame-Options: DENY
# Cache-Control: no-store, max-age=0
# Content-Security-Policy: frame-ancestors 'none'
# Referrer-Policy: no-referrer

Development

# Clone the repo
git clone https://github.com/mahdijafaridev/fastapi-middlewares.git
cd fastapi-middlewares

# Install dependencies
uv sync

# Run tests
pytest -v

# Run with coverage
pytest --cov=middlewares --cov-report=html

# Run example app
python examples/example_app.py

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE file for details.

Credits

Built with ❤️ for the FastAPI community.

Changelog

See CHANGELOG.md for release history.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_middlewares-0.1.1.tar.gz (17.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_middlewares-0.1.1-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_middlewares-0.1.1.tar.gz.

File metadata

  • Download URL: fastapi_middlewares-0.1.1.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastapi_middlewares-0.1.1.tar.gz
Algorithm Hash digest
SHA256 595586aeef02a5cee8829020eacd786db3c0353441e6544b497aef273ffd29fd
MD5 54a8153d77cf5896df7dee7a9505999c
BLAKE2b-256 2b5a93302c52f05836b9c303bb33001f6d3cdf1044d5045b6d6dc2f23bd87461

See more details on using hashes here.

File details

Details for the file fastapi_middlewares-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_middlewares-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 95763960057e7103befa9978f02206a276edcc8dc4cab26699270c07a7620324
MD5 f06d30b62989149b602d9c39079043e2
BLAKE2b-256 27297a801aac427ec6fb832790427fa8659d5808bdd6023590d2a0ad0df65c48

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page