Middleware & OpenAPI¶
This page covers ShieldMiddleware, which enforces route state on every HTTP request, and the two OpenAPI helpers that keep your /docs accurate at runtime.
ShieldMiddleware¶
ShieldMiddleware is a standard ASGI middleware (Starlette BaseHTTPMiddleware). Add it once to your ASGI app and it automatically intercepts every request, calls engine.check(), and returns the appropriate error response when a route is blocked. It works with any Starlette-compatible ASGI framework, including FastAPI.
Setup¶
from fastapi import FastAPI
from shield.fastapi import ShieldMiddleware
from shield.core.engine import ShieldEngine
engine = ShieldEngine()
app = FastAPI()
app.add_middleware(ShieldMiddleware, engine=engine)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
engine |
ShieldEngine |
required | The engine instance to delegate all check() calls to. Read more in ShieldEngine. |
responses |
dict \| None |
None |
App-wide custom response factories, keyed by error type. Read more in Custom responses. |
Request flow¶
Every incoming request passes through this sequence:
Incoming HTTP request
│
▼
ShieldMiddleware.dispatch()
│
├─ Path is /docs, /redoc, or /openapi.json? → pass through
├─ Path starts with /shield/ (admin)? → pass through
│
├─ Lazy-scan routes for __shield_meta__ (once, on first request)
│
├─ Route has force_active=True? → pass through
│
▼
engine.check(path, method)
│
├─ Global maintenance ON + path not exempt → 503 JSON
├─ MAINTENANCE → 503 JSON + Retry-After
├─ DISABLED → 503 JSON
├─ ENV_GATED (wrong environment) → 403 JSON
├─ DEPRECATED → call_next + inject headers
└─ ACTIVE → call_next ✓
Error responses¶
All error responses use a consistent JSON structure:
{
"error": {
"code": "MAINTENANCE_MODE",
"message": "This endpoint is temporarily unavailable",
"reason": "Database migration in progress",
"path": "GET:/payments",
"retry_after": "2025-06-01T04:00:00Z"
}
}
| Scenario | HTTP status | code field |
|---|---|---|
| Route in maintenance | 503 | MAINTENANCE_MODE |
| Route disabled | 503 | ROUTE_DISABLED |
| Global maintenance active | 503 | MAINTENANCE_MODE |
| Env-gated (wrong environment) | 403 | ENV_GATED |
Deprecation headers¶
For routes with status DEPRECATED, the middleware injects RFC-compliant headers without blocking the request. The response still reaches the client with a 200:
Custom responses
You can replace any of the default JSON error responses with HTML, redirects, or a different JSON shape — either per-route or globally on the middleware. Read more in Custom responses.
apply_shield_to_openapi (FastAPI only)¶
Keep your FastAPI OpenAPI schema accurate by filtering it based on the current route states at runtime. Disabled and env-gated routes are hidden. Maintenance routes are annotated. Deprecated routes are flagged.
Setup¶
from shield.fastapi.openapi import apply_shield_to_openapi
apply_shield_to_openapi(app, engine)
Call after app.include_router()
apply_shield_to_openapi patches app.openapi(). Call it after all routers have been included so the full route list is available when the patch is applied.
Parameters¶
| Parameter | Type | Description |
|---|---|---|
app |
FastAPI |
The FastAPI application instance to patch |
engine |
ShieldEngine |
The engine whose current state is used to filter the schema |
Schema behavior by route status¶
| Route status | OpenAPI schema behavior |
|---|---|
ACTIVE |
No change |
MAINTENANCE |
Summary prefixed with 🔧; description block shows a warning; x-shield-status extension added |
DISABLED |
Hidden from all schemas — not visible in /docs, /redoc, or /openapi.json |
ENV_GATED (wrong environment) |
Hidden from all schemas |
DEPRECATED |
Marked deprecated: true; successor path shown in description |
The schema is re-computed on every request to /openapi.json, so runtime state changes reflect immediately without a restart.
setup_shield_docs (FastAPI only)¶
Enhance FastAPI's /docs and /redoc with live status indicators that update automatically as route states change.
Setup¶
# apply_shield_to_openapi must be called first
apply_shield_to_openapi(app, engine)
setup_shield_docs(app, engine)
Parameters¶
| Parameter | Type | Description |
|---|---|---|
app |
FastAPI |
The FastAPI application instance |
engine |
ShieldEngine |
The engine whose state drives the UI indicators |
What it adds to /docs¶
| Condition | UI indicator |
|---|---|
| Global maintenance ON | Full-width pulsing red banner with the reason text and exempt paths; auto-refreshes every 15 seconds |
| Global maintenance OFF | Small green "All systems operational" chip in the bottom-right corner |
| Per-route maintenance | Orange left-border on the operation block with a 🔧 MAINTENANCE badge |
Use both together
apply_shield_to_openapi keeps the schema accurate (hiding disabled routes, marking deprecated ones). setup_shield_docs adds the live status UI on top. They are independent — use one, both, or neither.