Compose Routers¶
Use this guide when adding or relocating a route. The composition reference explains the complete application lifecycle and settings ownership; the startup route matrix is the canonical list of settings-driven surfaces.
Choose the Owner¶
Place the handler in the feature that owns its behavior:
- application JSON contracts belong under
app/api/v1/; - browser-session JSON transport belongs under
app/api/v1/browser_sessions/and is mounted at/api/v1/sessions; - external OAuth2 presentation adapters belong under
app/api/v1/oauth2_interactions/and are mounted at/api/v1/oauth2; - OAuth2 and OIDC protocol handlers belong under
app/oauth2/; - built-in authentication pages belong under
app/web/.
Do not move standardized OAuth2 or issuer-derived OIDC routes under /api/v1.
Choose the Composition Layer¶
Route composition has three layers:
- A leaf module defines handlers and exports a plain
routerwhen its route surface is static. - A feature composer exposes
create_*_router(settings)when settings or issuer-derived paths determine which leaf routers are present. app.main.create_app()mounts only top-level feature routers, middleware, exception handlers,/health/*, and optional static assets.
app/api/v1/router.py composes every v1 subrouter before /v1 is mounted once
by the API version boundary. Keep settings-driven route selection in the
feature composer. Do not read
settings again inside leaf modules to decide whether a route exists.
Add the Route¶
- Define one handler for each HTTP operation in the owning leaf module.
- Preserve typed FastAPI
Query,Form,Header,Cookie,Security, and dependency parameters so runtime validation and OpenAPI stay aligned. - Include the leaf router through its feature composer.
- Change
app/main.pyonly when adding or removing a top-level surface. - Add route-level behavior tests and an OpenAPI contract test when the transport contract changes.
Feature flags are evaluated when create_app() builds the application.
Changing environment variables or replacing app.state.settings afterward
does not alter mounted routes; construct a new application to apply a new
settings snapshot.