Application¶
app ¶
The generic SDMX-REST application factory.
A consumer standing up an SDMX-REST service gets the routes from the library;
the remaining work is the assembly. The middleware stack has an ordering
invariant whose violations are hard to spot: a ?lang= rewrite that lands
after the ETag layer hashes the wrong language, and a CORS preflight that
reaches the router answers 404. Mounted surfaces must share one runtime, or
each opens its own catalog. The multi-spec docs page is built by hand because
FastAPI's helper emits a single-spec page.
This module owns the assembly and leaves every catalog-shaped decision to the caller: which routers to include and in what order, what extra middleware to layer, which sub-apps to mount, and what to warm at startup.
See create_app. The ordering invariant is documented at its call to
_install_middleware; tests/test_middleware_invariants.py covers it
(#1).
RestSettings ¶
Configuration the generic app assembly needs — nothing catalog-specific.
A consumer's own settings object will carry far more (edition paths, log destinations, feature flags); map the relevant slice onto this.
Mount ¶
A sub-app mounted under the main app.
Mounted as a sub-app so it publishes its own
/openapi.json, which is what lets the docs page offer a spec dropdown.
The mount shares the parent's runtime — one catalog open serves every
surface — and receives a copy of the parent's state, because request
dependencies resolve against request.app, which is the sub-app for a
request that lands inside a mount.
spec_name labels it in the docs dropdown; None keeps it out.
MiddlewareSpec ¶
A middleware class plus its keyword arguments, applied at the outer slot.
create_app ¶
create_app(
runtime: CatalogRuntime,
settings: RestSettings,
*,
routers: Sequence[APIRouter] = (),
outer_middleware: Sequence[MiddlewareSpec] = (),
mounts: Sequence[Mount] = (),
state: Mapping[str, Any] | None = None,
perf_sink: Callable[..., None] | None = None,
on_startup: Callable[[FastAPI], Awaitable[None]]
| None = None,
on_shutdown: Callable[[], None] | None = None,
root_payload: Mapping[str, Any] | None = None,
) -> FastAPI
Assemble a FastAPI app serving SDMX-REST over runtime's catalog.
The catalog is opened once, on startup, and shared with every mount. The returned app is ordinary FastAPI — a consumer is free to keep mounting static files or including further routers afterwards.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime
|
CatalogRuntime
|
Carries the provider and every seam (splices, caches, filter shaper, annotator). Install those before calling; they are read per request, so later mutation works but is rarely what you want. |
required |
settings
|
RestSettings
|
The generic slice of configuration — see |
required |
routers
|
Sequence[APIRouter]
|
Routers to include, in order. Order is preserved because it
determines the order paths appear in the OpenAPI document. Use
|
()
|
outer_middleware
|
Sequence[MiddlewareSpec]
|
Extra middleware layered just inside CORS — i.e. outside everything else, so it observes the client's original request and the fully-encoded response. Logging taps belong here. |
()
|
mounts
|
Sequence[Mount]
|
Sub-apps to mount; each shares this app's runtime and state. |
()
|
state
|
Mapping[str, Any] | None
|
Attributes to stamp on |
None
|
perf_sink
|
Callable[..., None] | None
|
Sink for the perf-log middleware; |
None
|
on_startup
|
Callable[[FastAPI], Awaitable[None]] | None
|
Awaited after the catalog opens — the place for cache warmers. Exceptions propagate and will fail startup, so a best-effort warmer must swallow its own errors. |
None
|
on_shutdown
|
Callable[[], None] | None
|
Called after the app stops, instead of the default
|
None
|
root_payload
|
Mapping[str, Any] | None
|
JSON body for |
None
|
Returns:
| Type | Description |
|---|---|
FastAPI
|
The assembled app, with the catalog still closed until startup. |
library_routers ¶
The routers this library owns: structure, metadata, availability.
Returned in a sensible default order. A consumer that interleaves its own
routers should pass an explicit list to create_app instead — route
inclusion order is preserved verbatim and determines OpenAPI path order.