baldur.adapters.fastapi — FastAPI Adapter
fastapi_lifespan async context manager + BaldurMiddleware ASGI middleware.
The adapter intentionally stays thin — decisions live in
baldur.api.middleware; this wrapper only translates between FastAPI's
Request / Response and Baldur's RequestContext / ResponseContext.
The adapter manages no host-app authentication — your app owns endpoint auth, and Baldur's own admin server is gated by key-based roles. Unlike the Django adapter, it registers no Django permission groups.
See also
fastapi
FastAPI adapter for Baldur.
Provides:
- init_fastapi(app, service_name=None) — app-construction-time hook. Calls
baldur.init() exactly once and installs BaldurMiddleware via
app.add_middleware. Mirrors Flask's init_flask; the auto-wiring path
because an ASGI lifespan provably cannot add middleware after the stack is
built.
- fastapi_lifespan — async context manager for FastAPI's lifespan=
parameter. Calls baldur.init() on startup; admin server auto-starts
via the existing BALDUR_ADMIN_AUTOSTART flag in bootstrap.py.
- BaldurMiddleware — ASGI middleware that composes the framework-free
helpers from baldur.api.middleware (rate limit, admission / backpressure,
CB pre-flight + observation) into a single mountable middleware.
Install: pip install baldur-framework[fastapi]
Example
.. code-block:: python
from fastapi import FastAPI
from baldur.adapters.fastapi import fastapi_lifespan, init_fastapi
app = FastAPI(lifespan=fastapi_lifespan)
init_fastapi(app)
The adapter intentionally stays thin — every decision lives in
baldur.api.middleware. The wrapper only translates between FastAPI's
Request / Response and Baldur's RequestContext /
ResponseContext.
Status: Public
BaldurMiddleware
BaldurMiddleware(
app: Any,
service_name: str | None = None,
rate_limit: int | None = None,
window_seconds: int | None = None,
)
ASGI middleware integrating Baldur's middleware helpers.
Compatible with FastAPI's app.add_middleware(BaldurMiddleware, ...)
and Starlette's middleware stack. Pure ASGI — no FastAPI-specific
imports beyond the type hint, so the same class drops into any
Starlette-based app.
Exception handling: this middleware does not convert exceptions from
the downstream app. Starlette's ServerErrorMiddleware (installed by
default, outermost in the stack) is expected to catch unhandled
exceptions and emit the 500 response. As a consequence, if the
downstream raises before http.response.start is sent, this
middleware skips the CB observation — the error never reached the HTTP
surface this middleware observes.
init_fastapi
init_fastapi(
app: FastAPI,
service_name: str | None = None,
rate_limit: int | None = None,
window_seconds: int | None = None,
) -> None
Initialize Baldur for a FastAPI app.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
FastAPI
|
The FastAPI application instance (must be created before this call — middleware cannot be added once the ASGI stack is built). |
required |
service_name
|
str | None
|
Optional upstream identity. When supplied, CB pre-flight
+ post-response observation are enabled. When |
None
|
rate_limit
|
int | None
|
Per-instance override for the middleware rate limit
(requests per window). |
None
|
window_seconds
|
int | None
|
Per-instance window size override. |
None
|
fastapi_lifespan
async
fastapi_lifespan(
app: FastAPI,
) -> AsyncIterator[dict[str, Any]]
Initialize Baldur on app startup, drain on shutdown.
Yields an empty mapping so callers can attach lifespan-scoped state via
the standard lifespan_state pattern; the dict is reserved for
Baldur-internal use and may carry diagnostic state in future versions.