[HTTP]BodyA request or response body — two backings, one interface. A *chunk* is just a bytes-backed body, so .chunks yields [HTTP]Body too (bytes + .text/.json/.meta views): - bytes-backed: materialized Bytes + per-entity metadata (request bodies; a streamed chunk; an already-drained response). - stream-backed: a live ByteStream + framing ('chunked' / 'length' / 'close'); send builds these and the bytes are read lazily. Drain with .bytes/.text/.json (reads all, decodes any Content-Encoding, closes, caches) or stream with .chunks/.each: (one body per pull). Content-Encoding is whole-entity: a non-encoded body streams its raw transfer-chunks (each carrying its chunk extensions in .meta); a content-encoded body drains+decodes and streams as a single decoded chunk (streaming decode is a follow-up). Two server-side knobs on the stream backing: ownsStream=false leaves the stream open after a full drain (an [HTTP]Server request body must not close the connection the response goes out on), and maxBytes throws [HTTP]BodyTooLarge if a chunked body exceeds it cumulatively while draining (a length-framed body is preflighted instead).
A single streamed chunk: bytes-backed, carrying its per-chunk metadata (chunk extensions) and inheriting the response's media type.
The lowercased media type of a Content-Type header value, or nil for nil.
[HTTP]Body.mediaTypeOf:'application/json; charset=utf-8' "* -> application/json
A bytes-backed body over bytes with no declared content type.
([HTTP]Body.of:('hi'.asBytes)).text "* -> hi
A bytes-backed body over bytes, declaring its Content-Type.
A bytes-backed body over b, declaring a Content-Type and a Content-Encoding (request bodies, already-materialized responses).
stream-backed: a live stream framed as 'chunked' | 'length' (with len) | 'close'
stream-backed with the server-side knobs (see the class comment).
Drain the whole body: read every chunk, decode any Content-Encoding, close the stream, and cache. Idempotent — a second call returns the cached bytes.
A lazy Generator of body chunks — each yield is itself a bytes-backed [HTTP]Body (its .meta carries that chunk's extensions, .text/.json/.bytes its views). A non-encoded body streams its raw transfer-chunks; a content-encoded body can't be decoded chunk-by-chunk with the one-shot codecs (a transfer-chunk isn't a complete gzip/zstd frame), so it drains+decodes the whole entity and yields a single decoded chunk — true per-chunk streaming decode awaits a streaming (ByteStream) decompressor.
Close the underlying stream without draining (abandon a streamed response early).
Whether the body is already materialized (bytes-backed, or fully drained) — i.e. reading it costs nothing and touches no stream.
Iterate the body chunk by chunk — sugar for (.chunks).each: (see chunks).
Whether the drained body is zero bytes.
The Content-Encoding as received ('gzip', 'zstd', 'deflate'), or nil — bytes/text/json decode it transparently on drain.
Internal: populate the slots — bodies are built through the of:/over: class-side constructors, not new: directly.
Drain the whole body and parse it as JSON — regardless of declared media type; bad input throws a catchable ParseError.
Whether the declared media type mentions JSON.
The lowercased media type from Content-Type (e.g. 'application/json'), or nil when none was declared.
Per-entity metadata: a Map of chunk extensions for a streamed chunk, empty otherwise.
One chunk-extension value from .meta by name, or nil.
Internal: the wire-framing generator — a lazy Generator yielding the *raw* (still content-encoded) transfer-chunks, each itself a bytes-backed [HTTP]Body carrying its chunk extensions in .meta and the response's media type. A bytes-backed body yields itself once; stream-backed drives the chunked/length/close framing, closing the stream at EOF. .bytes drains this; the public .chunks decodes on top of it.
Human rendering: the backing ('N bytes' or 'stream') and the media type.
The body's size in bytes (drains a streamed body to count it).
Drain the whole body and read it as text — UTF-8, lossily (invalid sequences become U+FFFD; charset-aware decoding is a follow-up).