Module compression

Module compression 

Source
Expand description

Route-scoped response compression (DW-027, feature analysis 4.13).

One Compression policy per route drives two steps:

  • Negotiation (negotiate): the first algorithm of the policy’s preference order the request’s Accept-Encoding accepts wins. q=0 codings are treated as refusal; * accepts any. No acceptable overlap means no compression (identity is always permitted; the gateway never answers 406 over compression).
  • Encoding (wrap_response): the response body is wrapped in CompressedBody, which compresses CHUNK-BY-CHUNK — every data frame is written through the codec and flushed, and whatever the codec produced is forwarded as the next frame. The gateway never buffers a whole body to compress it; the only buffering is the codec’s own bounded working set plus the not-yet-emitted output of the current chunk. Per-chunk flushing costs a little ratio and buys streaming correctness: a slow/trickling upstream (SSE) reaches the client per chunk instead of at end-of-stream. Content types that must not be delayed (e.g. text/event-stream) are the operator’s call via excluded_content_types.

Response eligibility (see decide): never a 1xx/204/304, never a 101 upgrade, never a body that already carries Content-Encoding, never a zero length, never below min_size when the size is known (declared Content-Length or the exact size of the gateway’s own header-less bodies; unknown-length streams are always candidates). Content-Length is dropped on compression (the encoded length differs; framing switches to chunked/streamed), and Content-Encoding: <token> plus Vary: Accept-Encoding (merged into any existing Vary) are set. Vary is ALSO added to responses that were candidates but skipped (too small, wrong content type, no acceptable coding) so shared caches key them correctly alongside their compressed siblings — the proxy handles that half.

The three codecs are Write-based streaming encoders (flate2 gzip, brotli, zstd) all draining into one shared output sink the wrapper reads compressed bytes back out of; each carries the per-algorithm level clamp (gzip 0-9, brotli 0-11, zstd 0-22; defaults 6/5/3 — zstd 3 and brotli 5 sit at the fast end of their useful range, the right bias for a per-route default on a hot proxy path).

Structs§

CompressedBody
Compressing wrapper over a ProxyBody (DW-027). Streams: every inner data frame goes through the codec and comes back as (at most) one emitted frame of pending output; the codec is finished when the inner stream ends, and any trailing headers observed on the inner stream are re-emitted AFTER the compressed bytes (trailers ride after the body; compression does not touch them).
CompressionPlan
The negotiated coding for one response.

Functions§

decide
Decide whether THIS response gets compressed under the policy (DW-027): status, existing encoding, known size, content type, and negotiation all have to line up. None = pass through (the caller still adds Vary: Accept-Encoding for cache correctness).
negotiate
Negotiate the coding for one response (DW-027): the first policy algorithm the request accepts wins; None = serve identity.
wrap_response
Apply a plan to a response (DW-027): header rewrite + body wrap. Content-Length is removed (the encoded length differs); the encoding token and Vary: Accept-Encoding are set.