# Data flow — encode/starlette

> Canonical page: https://codevetter.com/unpack/starlette/data-flow

# Data flow — encode/starlette

Scanned commit 4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423 (2026-10-01). Generated by codevetter codevetter 1.15.0 on 2026-10-02.

Source inspection; upstream code and tests were not executed.

ASGI scope and message streams carry input through middleware and routing into connection objects. Parsing and rendering are generally lazy or explicit, with cached request bodies distinct from consumed streams. Uploads, lifespan state, and sessions have different ownership and cleanup boundaries. Outputs pass through send wrappers, which can modify headers, enforce limits, or collect telemetry before reaching the server.
- Router.app records scope['router'] and the selected route, then merges child_scope; Route.matches converts regex captures into typed path_params, while Mount.matches updates root_path and preserves app_root_path. — [starlette/routing.py#L244-L260](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/routing.py#L244-L260) [starlette/routing.py#L396-L427](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/routing.py#L396-L427) [starlette/routing.py#L678-L709](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/routing.py#L678-L709)
- Request.stream consumes http.request chunks until more_body is false and raises ClientDisconnect on disconnect; body joins and caches chunks, and json decodes that cached body with json.loads. — [starlette/requests.py#L234-L266](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/requests.py#L234-L266)
- Request._get_form dispatches by Content-Type; FormParser percent-decodes URL-encoded field names and values into FormData, enforcing field count and combined encoded name/value size through parser callbacks. — [starlette/requests.py#L268-L311](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/requests.py#L268-L311) [starlette/formparsers.py#L78-L102](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/formparsers.py#L78-L102) [starlette/formparsers.py#L108-L146](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/formparsers.py#L108-L146)
- Multipart filename parts become UploadFile objects backed by spooled temporary files; callbacks queue bytes, parse awaits writes and rewinds completed files, and UploadFile offloads writes that would roll onto disk. — [starlette/formparsers.py#L222-L245](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/formparsers.py#L222-L245) [starlette/formparsers.py#L274-L301](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/formparsers.py#L274-L301) [starlette/datastructures.py#L436-L470](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/datastructures.py#L436-L470)
- Multipart parsing closes all tracked temporary files on BaseException; successful form ownership passes to FormData, whose close method closes uploads, and Request.close delegates to it. — [starlette/formparsers.py#L293-L301](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/formparsers.py#L293-L301) [starlette/datastructures.py#L482-L497](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/datastructures.py#L482-L497) [starlette/requests.py#L313-L326](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/requests.py#L313-L326) [starlette/_utils.py#L92-L98](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/_utils.py#L92-L98)
- Router.lifespan merges yielded mappings into lifespan scope state; connection.state wraps the request scope dictionary, and TestClient copies app_state shallowly into HTTP and WebSocket scopes. — [starlette/routing.py#L650-L660](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/routing.py#L650-L660) [starlette/requests.py#L188-L196](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/requests.py#L188-L196) [starlette/testclient.py#L246-L277](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/testclient.py#L246-L277) [docs/lifespan.md#L73-L82](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/docs/lifespan.md#L73-L82)
- SessionMiddleware verifies timestamped cookie signatures and decodes base64 JSON into scope['session']; response-start handling adds Vary on access, signs modified nonempty sessions, and expires cleared existing sessions. — [starlette/middleware/sessions.py#L47-L91](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/middleware/sessions.py#L47-L91) [starlette/requests.py#L169-L176](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/requests.py#L169-L176)
- Response renders bytes before sending start/body messages, while StreamingResponse emits chunks with more_body; TestClient captures these messages into BytesIO and returns a buffered httpx-compatible Response, discarding HEAD bodies. — [starlette/responses.py#L34-L54](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/responses.py#L34-L54) [starlette/responses.py#L166-L173](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/responses.py#L166-L173) [starlette/responses.py#L251-L258](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/responses.py#L251-L258) [starlette/testclient.py#L316-L376](https://github.com/encode/starlette/blob/4e7fc04e5f2c69f60e418ff2107d0f6d9a0fe423/starlette/testclient.py#L316-L376)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

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