Request path
STATIC handles each parsed request as a Flow: request parts, an optional response, and metadata such as the selected profile, protocol labels, CSP nonce, and transport notes. An HTTP/2 stream gets its own Flow; it is not one Flow for the whole connection.
From socket to Flow
The browser sends a request to STATIC’s local listener. STATIC classifies the connection, builds a per-request Flow, runs request stages, and fetches from the origin. It then runs response stages before returning the result.
The listener first peeks at the incoming bytes. An HTTP CONNECT receives 200 Connection Established, then proceeds to a client-facing TLS handshake. A direct TLS connection enters that handshake immediately. A plain HTTP proxy request uses the HTTP/1.1 path without TLS interception. Unknown input is rejected. STATIC issues a certificate for the requested name from its own local CA during TLS interception.
After client TLS negotiation, h2 ALPN enters the HTTP/2 server path; other negotiated values enter HTTP/1.1. The browser-side protocol and the origin-side protocol are distinct. STATIC makes a new upstream request; it does not pass the browser’s TLS bytes directly to the website. See TLS and certificates.
What each stage changes
The ordered stages are HeaderProfileStage → BehavioralNoiseStage → CspStage → JsInjectionStage → AltSvcStage. Each stage has separate request, response-header, response-body, and finalization hooks; a stage may do nothing in a particular hook.
| Stage | Current responsibility |
|---|---|
| Header profile | Uses the explicit shared selection, attaches the validated effective policy, applies header rules, identity normalization and cache-sensitive request handling. |
| Behavioral noise | Creates a per-Flow plan and marks responses; the Rust augmentation of marked JSON bodies is still a placeholder, not a complete behavioral imitation. |
| CSP | Reads or generates a nonce and rewrites applicable response CSP after injection. |
| JS injection | Inserts the document runtime on eligible HTML and worker-specific bootstraps on eligible fetched JavaScript responses; records transformation/coverage outcomes. |
| Alt-Svc | Normalizes, redirects, or removes alternative-service advertisements according to configuration. |
The upstream fetcher receives the mutated request and any transport plan, performs the origin request, and returns a response. The response hooks then run before STATIC writes back to the browser. Request headers and HTML injection and CSP cover the mutations in detail.
Paths that differ
- HTTP/1.1 buffers an ordinary request and response before sending the staged response.
- HTTP/2 handles concurrent streams; it buffers HTML and script/bootstrap assets for possible mutation and streams other response bodies after header processing.
- Local document/module-worker runtime assets are served by STATIC without an origin fetch.
- Eligible worker entries retain their original URL and receive a response bootstrap; unsupported or cached/non-network paths have distinct limits.
- WebSocket upgrades use separate raw tunnel handling and bypass the ordinary response-body mutation path. Their upstream TLS path is not the same profile-driven
wreqfetcher.
Runtime insertion metadata is not proof of execution or full protection. Browser-side outcomes and realm restrictions are separate from the Rust listener/Flow being ready. See the runtime coverage.
Body size limits can end a Flow with an error rather than silently falling back to an unmodified response. Consult the connection handler, Flow model, and stage pipeline for the implementation.