# fastapi/fastapi — codebase unpack

> Canonical page: https://codevetter.com/unpack/fastapi

This is a deterministic Repo Unpack scan of fastapi/fastapi — a structural map, not a review, security audit, or maintainer-endorsed description.

- Scanned commit: 50113da16fec53b66b80d75e80a89296de4fa5a5 (2026-09-01)
- Last upstream commit: 📝 Update release notes
- Generated by codevetter 1.12.0 on 2026-09-22
- 2950 files scanned · 21.0 MB

## Languages

- Markdown: 1692 files
- Python: 1138 files
- YAML: 42 files
- HTML: 5 files
- Shell: 5 files
- JavaScript: 4 files
- CSS: 3 files
- TOML: 1 files

## Repository structure

- docs/ — 1733 files
- tests/ — 594 files
- docs_src/ — 464 files
- scripts/ — 68 files
- fastapi/ — 56 files
- .github/ — 28 files

Probable source entrypoint: `pyproject.toml` (inferred from the tree, not upstream docs)

## Package

- pyproject.toml: fastapi v{ source = "file", path = "fastapi/__init__.py" } — 56 declared dependencies

## Structural health signals

Average score 8.2/10 across 96 files; 12 hotspots. These are deterministic review leads, not proof of a bug.

## Recent history

- 50113da16fec (2026-09-01) 📝 Update release notes
- ad263df5a4a5 (2026-09-01) ⬆ Bump the python-packages group across 1 directory with 15 updates (#16285)
- 965b72225a48 (2026-09-01) 📝 Update release notes
- fcf472e93a26 (2026-09-01) ⬆ Bump starlette from 1.3.1 to 1.6.0 (#16289)
- fc5f36b17d0d (2026-09-01) 📝 Update release notes

## Overview

This is the FastAPI framework source repository at version 0.141.1 — a Pydantic v2-only, Starlette-based ASGI web framework whose distinguishing trick is deriving request parsing, validation, serialization and an OpenAPI 3.1 schema from ordinary Python type hints on endpoint functions. This tree is notably ahead of the classic FastAPI architecture: `include_router()` no longer flattens child routes into the parent but stores an `_IncludedRouter` wrapper resolved at match time, the package ships first-class Server-Sent Events (`fastapi/sse.py`) and JSON-Lines streaming, a `app.frontend()` / `router.frontend()` low-priority static-SPA router, and a bundled agent skill at `fastapi/.agents/skills/fastapi/SKILL.md`. The repo is overwhelmingly documentation and tests: 1692 Markdown files across 13 translated locales, 594 test files, and 464 runnable tutorial sources in `docs_src/` that the test suite executes directly. Its audience is Python API developers, and the repo itself enforces 100% line coverage, strict mypy, ty, and Ruff on every push.

## System map

The shipped artifact is the `fastapi/` package (~21k lines across 56 files), a thin-but-deep layer over Starlette and Pydantic v2. `fastapi/applications.py` defines the `FastAPI` app class (subclassing `starlette.applications.Starlette`) and `fastapi/routing.py` — the largest file at 6447 lines — defines `APIRouter`, `APIRoute`, the request handler factory, and the frontend static-file routing. There is no database or storage layer; the only persistent state is in-process route tables and the memoised OpenAPI schema. Everything else in the repo is supporting apparatus: `docs/` (13 locales), `docs_src/` (executable tutorial examples on `PYTHONPATH` during tests), `scripts/` (docs build, translation, release, sponsor tooling), and 23 GitHub Actions workflows. Deployment is a PyPI wheel built by pdm-backend and published via `uv publish` with OIDC trusted publishing; the docs deploy separately to Cloudflare Pages.
- The public API surface is re-exported from `fastapi/__init__.py`, which pins `__version__ = "0.141.1"` and exposes exactly 20 names including `FastAPI`, `APIRouter`, `Depends`, `Security`, `BackgroundTasks`, `UploadFile`, `HTTPException`, `WebSocketException` and Starlette's `status` module. — [fastapi/__init__.py#L1-25](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/__init__.py#L1-L25)
- `fastapi/routing.py` (6447 lines) and `fastapi/applications.py` (4774 lines) hold the bulk of the logic; `param_functions.py` is third at 2460 lines but is almost entirely `annotated_doc.Doc` docstrings for `Query`/`Path`/`Header`/`Body`/`Depends`. — [fastapi/routing.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py) [fastapi/applications.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py) [fastapi/param_functions.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/param_functions.py)
- Runtime boundaries are ASGI-only: `FastAPI.__call__` injects `root_path` into the scope then delegates to Starlette, and `build_middleware_stack()` composes `ServerErrorMiddleware` → user middleware → `ExceptionMiddleware` → `AsyncExitStackMiddleware` → `self.router`. — [fastapi/applications.py#L1020-1068](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1020-L1068) [fastapi/applications.py#L1160-1164](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1160-L1164)
- FastAPI-specific per-request state is carried in three ASGI scope keys holding `AsyncExitStack`s: `fastapi_middleware_astack` (set by `AsyncExitStackMiddleware` for closing uploaded files), plus `fastapi_inner_astack` and `fastapi_function_astack` set in the vendored `request_response`/`websocket_session` wrappers for request- and function-scoped `yield` dependencies. — [fastapi/middleware/asyncexitstack.py#L1-18](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/middleware/asyncexitstack.py#L1-L18) [fastapi/routing.py#L121-186](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L121-L186) [fastapi/dependencies/utils.py#L601-609](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L601-L609)
- Pydantic v1 support has been fully removed: `fastapi/_compat/__init__.py` re-exports only from `.shared` and `.v2`, and `PydanticV1NotSupportedError` is raised from `fastapi/encoders.py` and `fastapi/utils.py` when a v1 model is detected. — [fastapi/_compat/__init__.py#L1-40](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/_compat/__init__.py#L1-L40) [fastapi/exceptions.py#L246-250](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/exceptions.py#L246-L250) [fastapi/encoders.py#L342](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/encoders.py#L342) [fastapi/utils.py#L67](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/utils.py#L67)
- Validation is delegated to a single `ModelField` wrapper in `fastapi/_compat/v2.py` that owns a `pydantic.TypeAdapter` and exposes `validate`, `serialize` (dump_python) and `serialize_json` (dump_json). — [fastapi/_compat/v2.py#L114-235](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/_compat/v2.py#L114-L235)
- The CLI entrypoint `fastapi = "fastapi.cli:main"` is a shim that imports `fastapi_cli.cli.main` and raises a RuntimeError telling the user to `pip install "fastapi[standard]"` if the optional package is absent; `fastapi/__main__.py` calls the same function. — [pyproject.toml#L45-47](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L45-L47) [fastapi/cli.py#L1-13](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/cli.py#L1-L13) [fastapi/__main__.py#L1-3](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/__main__.py#L1-L3)
- Runtime dependencies are minimal and pinned by floor: `starlette>=0.46.0`, `pydantic>=2.9.0`, `typing-extensions>=4.8.0`, `typing-inspection>=0.4.2`, `annotated-doc>=0.0.2`, with Python >= 3.10 required. — [pyproject.toml#L12-52](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L12-L52)
- `fastapi/staticfiles.py`, `fastapi/templating.py`, `fastapi/testclient.py`, `fastapi/requests.py` and `fastapi/websockets.py` are one-to-three-line re-export shims over Starlette, so those integrations (Jinja2, httpx TestClient) are Starlette's, not FastAPI's. — [fastapi/staticfiles.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/staticfiles.py) [fastapi/templating.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/templating.py) [fastapi/testclient.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/testclient.py) [fastapi/websockets.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/websockets.py)
- Build/test/lint commands are shell scripts: `scripts/test.sh` runs `pytest -n auto --dist loadgroup tests scripts/tests/` with `PYTHONPATH=./docs_src`, `scripts/test-cov.sh` adds `--cov --cov-context=test`, and `scripts/lint.sh` runs `mypy fastapi`, `ty check`, `ruff check`, `ruff format --check`. — [scripts/test.sh](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/test.sh) [scripts/test-cov.sh](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/test-cov.sh) [scripts/lint.sh](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/lint.sh) [scripts/format.sh](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/format.sh)
- Release shape: `.github/workflows/publish.yml` triggers on GitHub release publication and runs `uv build` then `uv publish` with `id-token: write` (OIDC trusted publishing, no stored PyPI token). — [.github/workflows/publish.yml#L1-36](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/publish.yml#L1-L36)
- Docs deploy is a separate pipeline: `deploy-docs.yml` fires on `workflow_run` completion of Build Docs, downloads `docs-site-*` artifacts and pushes to Cloudflare Pages, reporting status through `scripts/deploy_docs_status.py`. — [.github/workflows/deploy-docs.yml#L1-60](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/deploy-docs.yml#L1-L60) [scripts/deploy_docs_status.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/deploy_docs_status.py)
- The package ships an agent skill inside the wheel at `fastapi/.agents/skills/fastapi/SKILL.md` with six reference pages (dependencies, path-operations, pydantic, responses, streaming, other-tools), making FastAPI conventions machine-consumable by coding agents. — [fastapi/.agents/skills/fastapi/SKILL.md](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/.agents/skills/fastapi/SKILL.md) [fastapi/.agents/skills/fastapi/references/streaming.md](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/.agents/skills/fastapi/references/streaming.md) [fastapi/.agents/skills/fastapi/references/dependencies.md](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/.agents/skills/fastapi/references/dependencies.md)

## Feature catalog

The user-facing feature set is the decorator API (`@app.get/put/post/delete/options/head/patch/trace`, `@app.websocket`, `@app.middleware`, `@app.exception_handler`), the parameter-declaration vocabulary (`Path`, `Query`, `Header`, `Cookie`, `Body`, `Form`, `File`, `Depends`, `Security`), the auto-generated OpenAPI 3.1 document plus Swagger UI and ReDoc pages, and seven built-in security schemes. This version adds three substantial features beyond classic FastAPI: Server-Sent Events via `response_class=EventSourceResponse`, JSON-Lines streaming from generator endpoints, and `app.frontend()` for serving built SPA assets as low-priority routes. Dependencies gained an explicit `scope` of `"function"` or `"request"`. Two response classes — `ORJSONResponse` and `UJSONResponse` — are now deprecated in favour of a Pydantic `dump_json` fast path.
- `FastAPI.setup()` registers up to four non-schema routes at construction: `openapi_url` (default `/openapi.json`), `docs_url` (`/docs`, Swagger UI), `swagger_ui_oauth2_redirect_url`, and `redoc_url` (`/redoc`); each is skipped when its URL is set to `None`. — [fastapi/applications.py#L1105-1158](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1105-L1158)
- All eight HTTP verb decorators plus `api_route`, `add_api_route`, `websocket`, `add_api_websocket_route`, `websocket_route`, `on_event`, `middleware`, `exception_handler` and `include_router` are defined on `FastAPI` and mirrored on `APIRouter`. — [fastapi/applications.py#L1301-4780](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1301-L4780) [fastapi/routing.py#L3133-3320](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L3133-L3320)
- Server-Sent Events: setting `response_class=EventSourceResponse` on a generator path operation makes the router encode each yielded item into SSE wire format via `format_sse_event`, set `Cache-Control: no-cache` and `X-Accel-Buffering: no`, and inject a `: ping` keepalive comment every `_PING_INTERVAL` (15s) of idleness. — [fastapi/sse.py#L20-33](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/sse.py#L20-L33) [fastapi/sse.py#L236-241](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/sse.py#L236-L241) [fastapi/routing.py#L519-627](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L519-L627)
- `ServerSentEvent` is a Pydantic model with `data`, `raw_data`, `event`, `id`, `retry`, `comment`; validators reject multi-line `event`/`id` values and null bytes in `id`, and a model validator forbids setting `data` and `raw_data` together. — [fastapi/sse.py#L36-157](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/sse.py#L36-L157)
- JSON-Lines streaming: when `is_json_stream` is set, generator endpoints are wrapped into a `StreamingResponse` with media type `application/jsonl`, each item serialized by `_serialize_data` and terminated with `\n`. — [fastapi/routing.py#L636-679](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L636-L679)
- `app.frontend(path, directory=..., fallback="auto", check_dir="auto")` serves a built SPA; API routes match first and the frontend is consulted only through `_match_low_priority`, with `fallback="auto"` preferring `404.html` and falling back to `index.html` only for navigation requests that accept `text/html`. — [fastapi/applications.py#L1222-1299](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1222-L1299) [fastapi/routing.py#L1944-1973](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1944-L1973) [fastapi/routing.py#L2037-2045](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2037-L2045)
- Seven security schemes ship in `fastapi/security/`: `APIKeyQuery`, `APIKeyHeader`, `APIKeyCookie`, `HTTPBasic`, `HTTPBearer`, `HTTPDigest`, `OAuth2` (with `OAuth2PasswordBearer` and `OAuth2AuthorizationCodeBearer`) and `OpenIdConnect`, plus the `OAuth2PasswordRequestForm` dependency and `SecurityScopes`. — [fastapi/security/__init__.py#L1-15](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/__init__.py#L1-L15) [fastapi/security/oauth2.py#L14-330](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/oauth2.py#L14-L330) [fastapi/security/api_key.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/api_key.py)
- Dependency scoping is a first-class feature: `params.Depends` is a frozen dataclass carrying `dependency`, `use_cache` and `scope: Literal["function", "request"] | None`, and `DependencyScopeError` is raised at `get_dependant` time if a request-scoped generator dependency depends on a function-scoped one. — [fastapi/params.py#L745-755](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/params.py#L745-L755) [fastapi/dependencies/utils.py#L302-317](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L302-L317) [fastapi/exceptions.py#L167-172](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/exceptions.py#L167-L172)
- `app.webhooks` is a dedicated `APIRouter` whose routes are documented under the OpenAPI `webhooks` key rather than `paths`. — [fastapi/applications.py#L936-948](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L936-L948) [fastapi/openapi/utils.py#L647-666](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/utils.py#L647-L666)
- `strict_content_type` (default `True`) is threaded from app → router → route → handler; when False, a body with no Content-Type header is still parsed as JSON. — [fastapi/applications.py#L996](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L996) [fastapi/routing.py#L390-394](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L390-L394) [fastapi/routing.py#L433-437](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L433-L437)
- `ORJSONResponse` and `UJSONResponse` are marked `@deprecated` with `FastAPIDeprecationWarning`, directing users to declare a return type so Pydantic serializes on the Rust side instead. — [fastapi/responses.py#L42-101](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/responses.py#L42-L101) [fastapi/exceptions.py#L252-256](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/exceptions.py#L252-L256)
- `app.dependency_overrides` is a plain dict on the app used as the `dependency_overrides_provider`; `solve_dependencies` re-derives a fresh `Dependant` for any overridden callable so the substitute's own signature is honoured. — [fastapi/applications.py#L966-985](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L966-L985) [fastapi/dependencies/utils.py#L621-637](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L621-L637)
- Repo-level developer features beyond the library: `scripts/docs.py` is a Typer CLI for building/serving the 13-locale docs site and generating `README.md` from `docs/en/docs/index.md`, and `scripts/translate.py` drives a `pydantic_ai.Agent("openai-chat:gpt-5.5")` to machine-translate docs pages. — [scripts/docs.py#L1-50](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/docs.py#L1-L50) [scripts/translate.py#L1-40](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/translate.py#L1-L40) [scripts/translate.py#L140](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/translate.py#L140)

## Data flow

Input arrives as an ASGI scope. Static declaration time happens first: at decoration, `get_dependant()` walks the endpoint signature with `analyze_param()` and sorts every parameter into `path_params`/`query_params`/`header_params`/`cookie_params`/`body_params`/`dependencies` on a `Dependant` dataclass, each field wrapped in a `ModelField` holding a Pydantic `TypeAdapter`. At request time the handler reads and decodes the body (form vs JSON vs raw bytes), then `solve_dependencies()` recursively resolves sub-dependencies, coerces each parameter group against its `ModelField`, and returns a `SolvedDependency` bundle of values, errors, background tasks and a mutable `Response`. Output flows back through `serialize_response()` (or the streaming serializers) and out as a Starlette `Response`. State owners are the router's route list, the memoised `app.openapi_schema`, and the per-request `AsyncExitStack`s in the ASGI scope.
- Body decoding branches on content type: form bodies go through `await request.form()` with `body.close` pushed onto the middleware exit stack; otherwise raw bytes are parsed as JSON only when the Content-Type maintype is `application` and the subtype is `json` or ends in `+json`, else passed through as bytes. — [fastapi/routing.py#L425-457](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L425-L457)
- A `json.JSONDecodeError` during body parsing is converted into a `RequestValidationError` with a synthetic `json_invalid` error at loc `("body", e.pos)`; any other parse exception becomes a 400 `HTTPException` with detail 'There was an error parsing the body'. — [fastapi/routing.py#L450-471](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L450-L471)
- `solve_dependencies()` resolves sub-dependencies depth-first before extracting path/query/header/cookie values, and memoises each result in `dependency_cache` keyed by `_get_cache_key` — a tuple of `(call, sorted oauth scopes, computed scope)` — so the same dependency called twice in one request runs once unless `use_cache=False`. — [fastapi/dependencies/utils.py#L618-681](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L618-L681) [fastapi/dependencies/models.py#L79-93](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/models.py#L79-L93)
- Generator dependencies are entered as context managers by `_solve_generator`: async generators via `asynccontextmanager`, sync generators via `contextmanager_in_threadpool`, and pushed onto `fastapi_inner_astack` unless the dependency declares `scope="function"`, in which case `fastapi_function_astack` is used so it tears down before the response is sent. — [fastapi/dependencies/utils.py#L566-576](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L566-L576) [fastapi/dependencies/utils.py#L666-676](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L666-L676) [fastapi/routing.py#L134-155](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L134-L155)
- `contextmanager_in_threadpool` deliberately gives `__exit__` its own `CapacityLimiter(1)` so a blocking teardown cannot deadlock against the shared AnyIO threadpool used by a connection pool inside the dependency. — [fastapi/concurrency.py#L17-41](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/concurrency.py#L17-L41)
- Form bodies flow through `_extract_form_body`, which reads `UploadFile` values into `bytes` when the declared annotation is bytes, expands sequence-of-bytes fields, and passes through any unmatched form keys as single values or lists. — [fastapi/dependencies/utils.py#L912-948](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L912-L948)
- `request_body_to_args` collapses to a single un-embedded field when `len(body_fields) == 1 and not embed_body_fields`, and in that case a `BaseModel`-annotated form body is exploded into its model fields before validation. — [fastapi/dependencies/utils.py#L951-1000](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L951-L1000)
- Response serialization has a fast path: when a `response_field` exists and no custom `response_class` was supplied, `serialize_response(dump_json=True)` calls `ModelField.serialize_json` and the bytes are wrapped in a bare `Response(media_type="application/json")`, skipping the dict → `json.dumps` round trip. — [fastapi/routing.py#L710-745](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L710-L745) [fastapi/routing.py#L301-340](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L301-L340) [fastapi/_compat/v2.py#L215-235](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/_compat/v2.py#L215-L235)
- Headers set on the injected `Response` object by dependencies are merged into the final response via `response.headers.raw.extend(solved_result.response.headers.raw)` on every branch (SSE, JSONL, raw stream, and normal). — [fastapi/routing.py#L624-627](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L624-L627) [fastapi/routing.py#L676](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L676) [fastapi/routing.py#L749](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L749)
- When `is_body_allowed_for_status_code(status_code)` is false (1xx, 204, 205, 304), the serialized body is discarded by setting `response.body = b""`. — [fastapi/routing.py#L746-748](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L746-L748) [fastapi/utils.py#L26-41](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/utils.py#L26-L41)
- Validation failures never reach the endpoint: `errors` accumulated by `solve_dependencies` short-circuit the handler and raise `RequestValidationError`, which the default handler renders as HTTP 422 with `{"detail": jsonable_encoder(exc.errors())}`. — [fastapi/routing.py#L752-756](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L752-L756) [fastapi/exception_handlers.py#L19-26](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/exception_handlers.py#L19-L26)
- The OpenAPI document is produced once and cached on `app.openapi_schema`, invalidated by comparing `self.router._get_routes_version()` — a recursive counter that sums `_routes_version` across all `_IncludedRouter` children — against `_openapi_routes_version`. — [fastapi/applications.py#L1070-1103](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1070-L1103) [fastapi/routing.py#L2573-2585](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2573-L2585)
- The SSE output path decouples generator iteration from the keepalive timer using two `anyio` memory object streams with `max_buffer_size=1`, a `_producer` task and a `_keepalive_inserter` task in a task group, so `anyio.fail_after` never wraps the user generator's `__anext__` directly. — [fastapi/routing.py#L552-599](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L552-L599)

## Behavior traces

Three flows dominate: application construction, a normal HTTP request, and OpenAPI generation. Construction is eager — dependants and response fields are computed at decoration time, so route registration errors surface at import. A request walks ASGI middleware, router matching (now indirected through `_IncludedRouter` for included routers), the exit-stack-wrapping `request_response` shim, dependency solving, endpoint invocation, and serialization. Streaming requests diverge at the handler into three branches (SSE, JSONL, raw generator). WebSockets follow a parallel but simpler path with no body parsing and no response serialization.
- Startup trace: `FastAPI.__init__` assigns metadata, asserts `title` and `version` when `openapi_url` is truthy, constructs `self.router = APIRouter(...)` with `dependency_overrides_provider=self`, seeds three default `exception_handlers`, and finally calls `self.setup()` which registers the `/openapi.json`, `/docs`, oauth2-redirect and `/redoc` routes. — [fastapi/applications.py#L873-1018](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L873-L1018) [fastapi/applications.py#L1105-1158](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1105-L1158)
- Route registration trace: `@app.get(...)` → `app.router.add_api_route` → `APIRoute.__init__` → `_populate_api_route_state(...)` (which builds `dependant`, `body_field`, `response_field`, `stream_item_field`, `unique_id`) → `self.app = request_response(self.get_route_handler())`. — [fastapi/routing.py#L1161-1224](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1161-L1224) [fastapi/routing.py#L961-1125](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L961-L1125)
- Lifespan trace: `APIRouter.app` routes `scope["type"] == "lifespan"` to `self.lifespan`; when no custom lifespan is given, `_DefaultLifespan` (re-vendored after Starlette removed it) calls `router._startup()` / `router._shutdown()` so `on_startup`/`on_shutdown` handlers still work, and `include_router` merges child lifespans via `_merge_lifespan_context`. — [fastapi/routing.py#L233-275](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L233-L275) [fastapi/routing.py#L2719-2725](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2719-L2725) [fastapi/routing.py#L3312-3319](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L3312-L3319)
- Matching trace for an included router: `APIRouter.app` iterates `self.routes`, an `_IncludedRouter` entry answers `matches()` by building `_EffectiveRouteContext` objects that apply the accumulated prefix/tags/dependencies, then `handle()` dispatches through `_handle_selected`. — [fastapi/routing.py#L1586-1803](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1586-L1803) [fastapi/routing.py#L2719-2740](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2719-L2740)
- Request trace (happy path): `request_response.app` creates the `Request`, opens `fastapi_inner_astack` and `fastapi_function_astack`, awaits the handler, sends the response, then asserts `response_awaited` — raising a `FastAPIError` naming the bare-`except`-in-a-yield-dependency footgun if the stack unwound without sending. — [fastapi/routing.py#L134-158](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L134-L158)
- Handler trace: `get_request_handler.app` → `_extract_endpoint_context(dependant.call)` → body read → `solve_dependencies(...)` → branch on `is_sse_stream` / `is_json_stream` / generator / plain → `run_endpoint_function` → `serialize_response` → `_build_response_args` → Response. — [fastapi/routing.py#L406-762](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L406-L762) [fastapi/routing.py#L344-373](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L344-L373)
- Sync endpoints are offloaded: `run_endpoint_function` calls `run_in_threadpool(dependant.call, **values)` when `_is_coroutine_callable(dependant.call)` is false, and `serialize_response` likewise runs `field.validate` in a threadpool for sync endpoints. — [fastapi/routing.py#L344-356](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L344-L356) [fastapi/routing.py#L305-311](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L305-L311)
- SSE trace: the generator is obtained, wrapped in `_sse_producer_cm()` entered on `fastapi_inner_astack` (so teardown is structured rather than via `GeneratorExit`), each item routed through `_serialize_sse_item` → `format_sse_event`, then yielded through `_sse_with_checkpoints` which `await anyio.sleep(0)` after each chunk so cancellation can be delivered. — [fastapi/routing.py#L519-630](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L519-L630)
- WebSocket trace: `websocket_session` opens the same two exit stacks, `get_websocket_app.app` builds an endpoint context labelled `WS <path>`, calls `solve_dependencies` with no body, raises `WebSocketRequestValidationError` on errors, and otherwise awaits the endpoint directly — there is no response serialization step. — [fastapi/routing.py#L165-190](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L165-L190) [fastapi/routing.py#L764-798](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L764-L798)
- WebSocket validation failures close the socket with code 1008 (`WS_1008_POLICY_VIOLATION`) and the encoded errors as the reason, via `websocket_request_validation_exception_handler`. — [fastapi/exception_handlers.py#L28-34](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/exception_handlers.py#L28-L34)
- Frontend fallback trace: `_FrontendStaticFiles.get_response` rejects non-GET/HEAD with 405 or 404, looks up the static resource, redirects directory hits missing a trailing slash, then applies the `404.html` / `index.html` fallback — the latter only if `_is_frontend_navigation_request` finds `text/html` or `application/xhtml+xml` with non-zero q in the Accept header. — [fastapi/routing.py#L1946-1973](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1946-L1973) [fastapi/routing.py#L2020-2045](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2020-L2045)
- OpenAPI trace: `app.openapi()` → `get_openapi(...)` → `get_fields_from_routes` (collects body/response/stream/param `ModelField`s across `iter_route_contexts`) → `get_flat_models_from_fields` → `get_model_name_map` → `get_definitions` → per-route `get_openapi_path` → `jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True)`. — [fastapi/openapi/utils.py#L551-679](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/utils.py#L551-L679)
- Docs page trace: a GET to `/docs` runs the closure registered in `setup()`, which prefixes `openapi_url` with the scope's `root_path` and calls `get_swagger_ui_html`, emitting an HTML page that loads Swagger UI from `https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/`. — [fastapi/applications.py#L1121-1137](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1121-L1137) [fastapi/openapi/docs.py#L79-92](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/docs.py#L79-L92) [fastapi/openapi/docs.py#L152-195](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/docs.py#L152-L195)

## Testing signals

Testing is the repo's centre of gravity: 594 files under `tests/`, 213 top-level `test_*.py` modules, plus `tests/test_tutorial/` mirroring the 77 directories of `docs_src/` so every documented example is executed. The stack is pytest 9 with `pytest-xdist` (`-n auto --dist loadgroup`), `anyio[trio]`, `inline-snapshot` (used in ~299 files), `dirty-equals` (~31 files), `pytest-timeout` at 20s, and `filterwarnings = ["error"]`. CI enforces `coverage report --fail-under=100` over `fastapi`, `tests` and `docs_src` combined, across a matrix of Windows/macOS/Ubuntu and Python 3.10–3.14t, including free-threaded builds and a Starlette-from-git leg. Performance has its own gates via CodSpeed wall-clock and memory benchmarks. The notable gap is that everything runs through the in-process `TestClient`; there is no test that boots a real uvicorn server.
- The test command is `pytest -n auto --dist loadgroup tests scripts/tests/` with `PYTHONPATH=./docs_src`, so tutorial modules are importable by name from the tutorial tests. — [scripts/test.sh#L1-7](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/test.sh#L1-L7) [tests/test_tutorial/test_security/test_tutorial001.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_tutorial/test_security/test_tutorial001.py)
- pytest is configured with `--strict-config --strict-markers --ignore=docs_src`, `strict_xfail = true`, `filterwarnings = ["error"]` and a 20-second per-test timeout, so any unexpected warning fails the suite. — [pyproject.toml#L186-196](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L186-L196)
- Coverage is measured over three source roots (`docs_src`, `tests`, `fastapi`) with `parallel = true` and per-runner `CONTEXT`, and the `coverage-combine` CI job ends with `coverage report --fail-under=100`. — [pyproject.toml#L198-220](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L198-L220) [.github/workflows/test.yml#L300-340](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/test.yml#L300-L340)
- The CI matrix covers Windows and macOS on Python 3.14 and 3.14t (free-threaded) plus targeted Ubuntu/macOS legs for 3.10 (with `uv-resolution: lowest-direct` and a forced `pydantic==2.9.0`), 3.12, 3.13 and 3.14, and a `starlette-git` leg installing Starlette from main. — [.github/workflows/test.yml#L48-130](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/test.yml#L48-L130)
- A dedicated `regression-test` job checks out the PR base revision, applies only the PR's test diff, and warns via `::warning::` if the changed tests already pass without the code change — an automated 'does this test actually prove the fix' gate. — [.github/workflows/test.yml#L200-290](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/test.yml#L200-L290)
- Performance regressions are gated by two CodSpeed jobs: `pytest tests/benchmarks --codspeed` in simulation mode and `pytest tests/memory_benchmarks --codspeed` in memory mode. — [.github/workflows/test.yml#L160-198](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/test.yml#L160-L198) [tests/benchmarks/test_general_performance.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/benchmarks/test_general_performance.py) [tests/memory_benchmarks/test_dependency_graph.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/memory_benchmarks/test_dependency_graph.py)
- `inline-snapshot` is the dominant assertion style for OpenAPI and error payloads, appearing in roughly 299 test files, with CI setting `INLINE_SNAPSHOT_DEFAULT_FLAGS: review` to prevent silent snapshot rewrites. — [.github/workflows/test.yml#L14-17](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/test.yml#L14-L17) [tests/test_security_http_basic_realm.py#L1-40](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_security_http_basic_realm.py#L1-L40)
- The new frontend feature is densely covered: `tests/test_frontend.py` has 40+ tests including Accept-header q-value parsing, path-segment boundary matching, trailing-slash normalization, dependency ordering across nested `include_router`, and `PermissionError`/`ENAMETOOLONG` lookup failures. — [tests/test_frontend.py#L37-860](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_frontend.py#L37-L860)
- Streaming has dedicated suites for SSE (`tests/test_sse.py`), cancellation (`tests/test_stream_cancellation.py`), item validation errors (`tests/test_stream_json_validation_error.py`), bare types and status codes, plus tutorial tests under `tests/test_tutorial/test_server_sent_events` and `test_stream_json_lines`. — [tests/test_sse.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_sse.py) [tests/test_stream_cancellation.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_stream_cancellation.py) [tests/test_stream_json_validation_error.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_stream_json_validation_error.py) [tests/test_tutorial/test_server_sent_events](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_tutorial/test_server_sent_events)
- Security coverage is per-scheme and per-variant — around 30 files spanning `test_security_http_basic*`, `test_security_api_key_*`, `test_security_oauth2*`, `test_security_scopes*`, `test_security_openid_connect*`, plus `test_webhooks_security.py` and `test_top_level_security_scheme_in_openapi.py`. — [tests/test_security_scopes.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_security_scopes.py) [tests/test_security_oauth2.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_security_oauth2.py) [tests/test_security_api_key_cookie.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_security_api_key_cookie.py) [tests/test_webhooks_security.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_webhooks_security.py)
- Performance claims in the code are pinned by behavioural tests: `tests/test_dump_json_fast_path.py` patches `starlette.responses.json.dumps` and asserts it is never called on the default-response-class path. — [tests/test_dump_json_fast_path.py#L29-45](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_dump_json_fast_path.py#L29-L45) [fastapi/routing.py#L710-745](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L710-L745)
- Static analysis is part of the gate, not optional: `.pre-commit-config.yaml` runs ruff check/format, `mypy fastapi` (with `strict = true`), `ty check` (`error-on-warning = true`), typos, and `zizmor` over `.github/workflows/`. — [.pre-commit-config.yaml#L20-105](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.pre-commit-config.yaml#L20-L105) [pyproject.toml#L160-166](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L160-L166) [pyproject.toml#L296-298](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L296-L298)
- `tests/main.py` is a shared 'kitchen sink' app used by several suites, registering `api_route`, `add_api_route`, path converters and enum/http-status params against a single `FastAPI(openapi_external_docs=...)` instance. — [tests/main.py#L1-45](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/main.py#L1-L45)
- Uncovered by the suite: no test exercises a real ASGI server process — every HTTP assertion goes through Starlette's in-process `TestClient`, so uvicorn/h11 interactions (real backpressure, client disconnect over a socket) are untested here. (inferred) — [fastapi/testclient.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/testclient.py) [tests/test_sse.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_sse.py) [tests/test_stream_cancellation.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_stream_cancellation.py)

## Risk map

As a library, the dangerous surfaces are file IO (the new frontend static server), auth scheme edge cases, and the streaming/exit-stack machinery where resource teardown is subtle. The frontend server is the newest and widest-blast-radius addition: it reads arbitrary files from a user-supplied directory on every unmatched request. The included-router rework is the deepest structural change and introduces a per-request handler rebuild plus a ContextVar hand-off that the code itself flags as temporary. Two caches — `_endpoint_context_cache` and the `lru_cache`d callable classifiers — are keyed by object identity, which is correct only as long as the keyed objects outlive the cache. Repo-level supply-chain risk is actively managed: all Actions are SHA-pinned, `permissions: {}` is the default, `persist-credentials: false` on every checkout, and zizmor lints the workflows.
- `_FrontendStaticFiles` serves files from a user-supplied directory on every request that no API route matched; it mitigates traversal by normalizing the path (`os.path.normpath(os.path.join(*path.split("/")))`), delegating to Starlette's `lookup_path`, and passing `follow_symlink=False`, but the blast radius of a bug here is arbitrary file disclosure. — [fastapi/routing.py#L1899-1940](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1899-L1940) [fastapi/routing.py#L1974-1985](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1974-L1985)
- `_lookup_path` maps a `PermissionError` on the filesystem to an HTTP 401 response, which conflates a server-side filesystem permission problem with a client authentication failure and can leak the existence of unreadable paths. — [fastapi/routing.py#L1974-1985](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1974-L1985)
- `APIRoute.handle` rebuilds the entire request handler — `request_response(self.get_route_handler())`, which re-runs `get_request_handler` — on every single request whenever an `_EffectiveRouteContext` is present, i.e. for all routes reached through `include_router`. — [fastapi/routing.py#L1261-1284](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1261-L1284) [fastapi/routing.py#L1225-1250](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1225-L1250)
- The effective-route context is passed from `handle()` to `get_route_handler()` through a module-level ContextVar rather than an argument, and the code carries a `TODO: Replace or deprecate this no-scope hook` — any subclass overriding `get_route_handler()` interacts with this implicitly. — [fastapi/routing.py#L1225-1233](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1225-L1233)
- `_endpoint_context_cache` is an unbounded module-level `dict[int, EndpointContext]` keyed by `id(func)`; entries are never evicted, so a process that creates endpoint callables dynamically grows the dict without bound and could in principle collide on a recycled `id`. — [fastapi/routing.py#L275-300](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L275-L300)
- The callable classifiers `_is_gen_callable`/`_is_async_gen_callable`/`_is_coroutine_callable` use `lru_cache(maxsize=4096)` keyed by a `_CallIdentity` whose `__hash__` is `id(self.call)`, so the cache holds a strong reference to every classified callable and identity reuse after GC is the correctness assumption. — [fastapi/dependencies/models.py#L55-65](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/models.py#L55-L65) [fastapi/dependencies/models.py#L130-160](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/models.py#L130-L160)
- `HTTPBasic.__call__` base64-decodes the Authorization header and splits on `:`; it returns the raw username and password with no timing-safe comparison anywhere in the framework — constant-time credential checking is left entirely to the application. — [fastapi/security/http.py#L202-220](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/http.py#L202-L220)
- Every security scheme has an `auto_error=False` mode that returns `None` instead of raising 401; a dependency written against that mode that forgets to check for `None` silently authenticates everyone. — [fastapi/security/oauth2.py#L423-431](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/oauth2.py#L423-L431) [fastapi/security/http.py#L94-104](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/http.py#L94-L104) [fastapi/security/http.py#L303-317](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/http.py#L303-L317)
- The default Swagger UI and ReDoc pages load JavaScript and CSS from `cdn.jsdelivr.net` (and Google Fonts for ReDoc) with no SRI hashes, so `/docs` and `/redoc` execute third-party CDN code by default in every FastAPI app. — [fastapi/openapi/docs.py#L79-92](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/docs.py#L79-L92) [fastapi/openapi/docs.py#L236](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/docs.py#L236) [fastapi/openapi/docs.py#L275](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/docs.py#L275)
- Swagger UI parameter injection is defended by `_html_safe_json`, which escapes `<`, `>` and `&` before interpolating user-supplied `swagger_ui_parameters` and `init_oauth` into a `<script>` block — but `oauth2_redirect_url` is interpolated into the same script with no escaping. — [fastapi/openapi/docs.py#L9-19](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/docs.py#L9-L19) [fastapi/openapi/docs.py#L178-181](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/docs.py#L178-L181)
- `_extract_endpoint_context` calls `inspect.getsourcefile` and `getsourcelines`, embedding absolute server file paths into `ValidationException.__str__`; these appear in logs and in `ResponseValidationError` tracebacks but not in the 422 JSON body, which only serializes `exc.errors()`. — [fastapi/routing.py#L278-299](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L278-L299) [fastapi/exceptions.py#L192-210](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/exceptions.py#L192-L210) [fastapi/exception_handlers.py#L19-26](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/exception_handlers.py#L19-L26)
- `request_response` detects a swallowed exception in a `yield` dependency only after the fact, by checking a `response_awaited` flag and raising a `FastAPIError` with a docs link — a heuristic guard rather than a structural fix. — [fastapi/routing.py#L137-158](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L137-L158)
- `scripts/translate.py` sends documentation content to OpenAI through `pydantic_ai.Agent("openai-chat:gpt-5.5")`, and `.github/workflows/translate.yml` supplies `OPENAI_API_KEY` from repo secrets with two `zizmor: ignore[secrets-outside-env]` suppressions. — [scripts/translate.py#L140](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/translate.py#L140) [.github/workflows/translate.yml#L112-118](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/translate.yml#L112-L118)
- Two workflows use elevated triggers with explicit zizmor suppressions: `guard-dependencies.yml` runs on `pull_request_target` (mitigated by never checking out PR code and only reading `context.payload`), and `deploy-docs.yml`/`smokeshow.yml` run on `workflow_run`. — [.github/workflows/guard-dependencies.yml#L1-14](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/guard-dependencies.yml#L1-L14) [.github/workflows/deploy-docs.yml#L1-9](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/deploy-docs.yml#L1-L9) [.github/workflows/smokeshow.yml#L1-9](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/smokeshow.yml#L1-L9)
- Legacy/deprecated code still present: `openapi_prefix` (warns and aliases to `root_path`), `on_event`, `_DefaultLifespan` re-vendored after Starlette deleted it, and the deprecated `ORJSONResponse`/`UJSONResponse` pair kept only for compatibility. — [fastapi/applications.py#L926-935](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L926-L935) [fastapi/applications.py#L4662-4682](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L4662-L4682) [fastapi/routing.py#L250-275](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L250-L275) [fastapi/responses.py#L42-101](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/responses.py#L42-L101)

## Extension points

FastAPI's extension model is almost entirely composition and subclassing rather than registries. The three canonical hooks are `route_class` on `APIRouter` (swap `APIRoute` for a subclass overriding `get_route_handler`), `dependency_overrides` (a dict keyed by the original callable), and `exception_handlers` (a dict keyed by exception type or status code). Beyond those, `SecurityBase` is the contract for new auth schemes, `generate_unique_id_function` controls operation IDs for client generators, `default_response_class` and `response_class` control output encoding, and `openapi_extra` plus overriding `app.openapi()` let you post-process the schema. The `DefaultPlaceholder`/`Default()` sentinel is the mechanism that lets app → router → route parameter inheritance distinguish 'not set' from 'explicitly set to the default value'.
- `APIRouter(route_class=...)` accepts any `APIRoute` subclass; the documented pattern is to override `get_route_handler()` to wrap the returned coroutine, and `tests/test_custom_route_class.py` plus `docs_src/custom_request_and_route/` exercise it. — [fastapi/routing.py#L2560-2566](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2560-L2566) [fastapi/routing.py#L1225-1250](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1225-L1250) [tests/test_custom_route_class.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_custom_route_class.py)
- New authentication schemes plug in by subclassing `SecurityBase` — a two-attribute protocol (`model: SecurityBaseModel`, `scheme_name: str`) — which `_is_security_scheme` detects via `isinstance` on the unwrapped callable to feed OpenAPI `securitySchemes`. — [fastapi/security/base.py#L1-7](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/security/base.py#L1-L7) [fastapi/dependencies/models.py#L118-128](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/models.py#L118-L128) [fastapi/openapi/utils.py#L132-158](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/utils.py#L132-L158)
- `dependency_overrides` is the testing seam: any object with a `.dependency_overrides` dict can be passed as `dependency_overrides_provider`, and `solve_dependencies` rebuilds the `Dependant` from the substitute callable so its own parameters are resolved. — [fastapi/applications.py#L966-985](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L966-L985) [fastapi/dependencies/utils.py#L621-637](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L621-L637) [tests/test_dependency_overrides.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_dependency_overrides.py)
- `exception_handlers` is a mutable dict keyed by exception class or the ints 500 / `Exception`; `build_middleware_stack` splits the 500/`Exception` entry out as `ServerErrorMiddleware`'s handler and hands the rest to `ExceptionMiddleware`. — [fastapi/applications.py#L1000-1017](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1000-L1017) [fastapi/applications.py#L1020-1040](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1020-L1040)
- `generate_unique_id_function` (default `generate_unique_id`, which slugifies `route.name + path_format + method`) is inheritable app → router → route and is the hook for client-generator-friendly operation IDs. — [fastapi/utils.py#L95-101](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/utils.py#L95-L101) [fastapi/routing.py#L1348-1358](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1348-L1358) [tests/test_tutorial/test_generate_clients](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_tutorial/test_generate_clients)
- The `DefaultPlaceholder` / `Default()` pattern plus `get_value_or_default` is how a router's setting overrides an app's only when explicitly provided — `Default(JSONResponse)` is not the same as passing `JSONResponse`. — [fastapi/datastructures.py#L153-180](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/datastructures.py#L153-L180) [fastapi/utils.py#L121-136](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/utils.py#L121-L136) [fastapi/routing.py#L1329-1360](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1329-L1360)
- `_RouterIncludeContext.for_include` and `.combine` are the single place where inherited router attributes (prefix, tags, dependencies, responses, callbacks, deprecated, include_in_schema, unique-id fn, strict_content_type) are merged — new inheritable router options must be added to both methods. — [fastapi/routing.py#L1306-1371](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1306-L1371)
- `_low_priority_routes` on `APIRouter` is a general extension slot, not frontend-specific: `frontend()` appends a `_FrontendRouteGroup` to it, and `_match_low_priority` consults the list only after normal matching and redirect-slashes handling fail. — [fastapi/routing.py#L2566-2569](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2566-L2569) [fastapi/routing.py#L2705-2718](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2705-L2718) [fastapi/routing.py#L2762-2780](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2762-L2780)
- Custom response encodings plug in by subclassing `starlette.responses.Response` and passing it as `response_class`; `EventSourceResponse` is itself just such a marker subclass, detected with `lenient_issubclass(actual_response_class, EventSourceResponse)`. — [fastapi/sse.py#L20-33](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/sse.py#L20-L33) [fastapi/routing.py#L395-397](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L395-L397)
- OpenAPI can be extended at three levels: per-operation `openapi_extra` on a route, whole-document post-processing by reassigning `app.openapi`, and swapping the `openapi_url`/`docs_url`/`redoc_url` routes by passing `None` and registering your own. — [fastapi/routing.py#L1207-1208](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1207-L1208) [fastapi/applications.py#L1070-1103](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1070-L1103) [docs_src/extending_openapi](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/docs_src/extending_openapi) [docs_src/custom_docs_ui](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/docs_src/custom_docs_ui)
- `jsonable_encoder` accepts `custom_encoder` and `sqlalchemy_safe`, and the class→encoder mapping is precomputed by `generate_encoders_by_class_tuples(ENCODERS_BY_TYPE)`, which is the hook for adding new type serializers. — [fastapi/encoders.py#L53-128](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/encoders.py#L53-L128) [fastapi/encoders.py#L129-200](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/encoders.py#L129-L200)
- Middleware plugs in three ways: the `middleware=[Middleware(...)]` constructor argument, `app.add_middleware(...)`, and the `@app.middleware("http")` decorator which wraps the function in `BaseHTTPMiddleware`. — [fastapi/applications.py#L4683-4728](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L4683-L4728) [fastapi/applications.py#L1041-1052](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1041-L1052)
- For agent tooling specifically, the extension point is `fastapi/.agents/skills/fastapi/` — adding a new `references/*.md` page and linking it from `SKILL.md`'s Quick Reference list is how new guidance is surfaced, and the directory ships inside the installed package. (inferred) — [fastapi/.agents/skills/fastapi/SKILL.md](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/.agents/skills/fastapi/SKILL.md) [fastapi/.agents/skills/fastapi/references/path-operations.md](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/.agents/skills/fastapi/references/path-operations.md)

## Contributor handoff

Read `fastapi/.agents/skills/fastapi/SKILL.md` first — it is the project's own statement of intended API style and is authoritative for any user-facing example you write. Then read `fastapi/routing.py` (specifically `get_request_handler`, `include_router`, and the `_IncludedRouter`/`_EffectiveRouteContext` pair) and `fastapi/dependencies/utils.py` (`get_dependant`, `analyze_param`, `solve_dependencies`), because nearly every behavioural change lands in one of those. The hard constraints are 100% coverage, strict mypy plus ty, `filterwarnings = ["error"]`, and `inline-snapshot` review mode — a change that is functionally right but leaves a line uncovered or emits a warning will fail CI. Dependency files are off-limits to non-org contributors and enforced by a workflow that auto-closes such PRs.
- Read first, in order: `fastapi/.agents/skills/fastapi/SKILL.md` (conventions), `fastapi/applications.py#L873-1164` (app construction), `fastapi/routing.py#L375-762` (the request handler), `fastapi/dependencies/utils.py#L271-733` (dependency graph + solving), `fastapi/_compat/v2.py#L114-235` (ModelField). — [fastapi/.agents/skills/fastapi/SKILL.md](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/.agents/skills/fastapi/SKILL.md) [fastapi/applications.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py) [fastapi/routing.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py) [fastapi/dependencies/utils.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py) [fastapi/_compat/v2.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/_compat/v2.py)
- Run `bash scripts/test.sh` for the suite and `bash scripts/lint.sh` before proposing a change; `scripts/format.sh` applies `ruff --fix` and `ruff format` across `fastapi tests docs_src scripts`. — [scripts/test.sh](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/test.sh) [scripts/lint.sh](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/lint.sh) [scripts/format.sh](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/format.sh)
- Any new library code must be covered — CI runs `coverage report --fail-under=100` over `fastapi`, `tests` and `docs_src` combined, so genuinely unreachable branches need an explicit `# pragma: no cover` (the existing convention in `fastapi/dependencies/models.py`). — [.github/workflows/test.yml#L300-340](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/test.yml#L300-L340) [pyproject.toml#L198-220](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L198-L220) [fastapi/dependencies/models.py#L140-146](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/models.py#L140-L146)
- New documentation examples belong in `docs_src/<topic>/tutorialNNN_py310.py` with a matching `tests/test_tutorial/test_<topic>/test_tutorialNNN.py`; `docs_src` is on `PYTHONPATH` during tests and excluded from pytest collection. — [scripts/test.sh#L5-6](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/test.sh#L5-L6) [pyproject.toml#L189](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L189) [tests/test_tutorial/test_security/test_tutorial001.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_tutorial/test_security/test_tutorial001.py)
- Snapshot assertions must not be silently regenerated: CI sets `INLINE_SNAPSHOT_DEFAULT_FLAGS: review`, and the `[tool.inline-snapshot]` fix/create flags in `pyproject.toml` are commented out on purpose. — [.github/workflows/test.yml#L14-17](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/test.yml#L14-L17) [pyproject.toml#L263-266](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L263-L266)
- Do not edit `pyproject.toml` or `uv.lock` on behalf of an outside contributor: `guard-dependencies.yml` auto-comments and closes any PR touching them unless the author is an org MEMBER/OWNER or `dependabot[bot]`. — [.github/workflows/guard-dependencies.yml#L15-50](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.github/workflows/guard-dependencies.yml#L15-L50)
- Only `docs/en/` is hand-edited; the `ensure-non-translated` pre-commit hook rejects modifications to non-English docs outside the translated set, and `README.md` is generated from `docs/en/docs/index.md` by the `generate-readme` hook. — [.pre-commit-config.yaml#L60-90](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/.pre-commit-config.yaml#L60-L90) [scripts/docs.py#L40-55](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/docs.py#L40-L55)
- Trap: `include_router` no longer copies routes. Code that assumes `app.routes` is a flat list of `APIRoute` objects will silently miss included routes — iterate with `routing.iter_route_contexts(routes)` and unwrap via `RouteContext`, the way `get_fields_from_routes` does. — [fastapi/routing.py#L3305-3311](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L3305-L3311) [fastapi/routing.py#L1828-1852](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L1828-L1852) [fastapi/openapi/utils.py#L551-582](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/openapi/utils.py#L551-L582)
- Trap: after adding or mutating routes at runtime you must go through `add_route`/`add_api_route`/`include_router`/`frontend`, all of which call `_mark_routes_changed()`; appending directly to `router.routes` will leave the cached `app.openapi_schema` stale. — [fastapi/routing.py#L2570-2585](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L2570-L2585) [fastapi/applications.py#L1084-1103](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/applications.py#L1084-L1103)
- Trap: three distinct `AsyncExitStack`s live in the scope with different lifetimes — `fastapi_middleware_astack` (files), `fastapi_inner_astack` (request-scoped yield deps and the SSE producer), `fastapi_function_astack` (function-scoped yield deps). Picking the wrong one changes when teardown runs relative to the response being sent. — [fastapi/middleware/asyncexitstack.py#L10-18](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/middleware/asyncexitstack.py#L10-L18) [fastapi/routing.py#L134-155](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L134-L155) [fastapi/dependencies/utils.py#L601-609](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L601-L609) [fastapi/dependencies/utils.py#L666-676](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/dependencies/utils.py#L666-L676)
- Trap: every new streaming code path needs an `await anyio.sleep(0)` checkpoint after each yielded chunk, or client-disconnect cancellation is never delivered — the existing sites cite issue #14680. — [fastapi/routing.py#L605-614](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L605-L614) [fastapi/routing.py#L650-656](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L650-L656) [fastapi/routing.py#L690-698](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/routing.py#L690-L698)
- Safe edit boundary: `fastapi/staticfiles.py`, `fastapi/templating.py`, `fastapi/testclient.py`, `fastapi/requests.py`, `fastapi/websockets.py`, `fastapi/logger.py` and `fastapi/middleware/*.py` (except `asyncexitstack.py`) are pure re-exports — behaviour changes belong upstream in Starlette, not here. — [fastapi/staticfiles.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/staticfiles.py) [fastapi/requests.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/requests.py) [fastapi/middleware/__init__.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/middleware/__init__.py) [fastapi/logger.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/logger.py)
- Style conventions to match: parameters documented with `Annotated[..., Doc("""...""")]` from `annotated_doc`, `from __future__` never used (ruff keeps runtime typing), PEP 604 unions throughout, and `from x import Y as Y` re-export form in `__init__.py` files (which are exempt from F401). — [fastapi/param_functions.py](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/param_functions.py) [fastapi/__init__.py#L5-25](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/fastapi/__init__.py#L5-L25) [pyproject.toml#L241-260](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/pyproject.toml#L241-L260)
- The suite runs under pytest-xdist with `--dist loadgroup`; module-level `app = FastAPI()` plus `client = TestClient(app)` is the established per-file pattern, so avoid cross-file shared mutable state. — [scripts/test.sh#L6](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/scripts/test.sh#L6) [tests/test_dump_json_fast_path.py#L14-27](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_dump_json_fast_path.py#L14-L27) [tests/test_security_http_basic_realm.py#L8-19](https://github.com/fastapi/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/tests/test_security_http_basic_realm.py#L8-L19)

Source repository: https://github.com/fastapi/fastapi
Full evidence corpus: https://github.com/Codevetter/codevetter/tree/main/benchmarks/repo-unpacks/fastapi.json

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
