WEB / WEB-07.04
Framing, compression, and negotiation
The same Çay representation can appear as 4-byte identity content, 24-byte gzip content, or a chunked message. Selection, transformation, and boundaries are separate layers.
1. Core · Mechanism
Read every scenario without motion
Gzip + Content-Length
- Preferences prepared
Media and coding preferences are distinct, not authentication evidence.
- Browser / Duru
- GET /tea-label ready; text/plain / gzip;q=1, identity;q=0.5; awaiting response
- Atlas selection and encoder
- No request
- Representation inventory
- Representation: Çay; 4 bytes
- GET arrived
The Application received Accept and Accept-Encoding without selecting a representation yet.
- Browser / Duru
- GET /tea-label ready; text/plain / gzip;q=1, identity;q=0.5; awaiting response
- Atlas selection and encoder
- Preferences received
- Representation inventory
- Representation: Çay; 4 bytes
- Variant selection
The fixture selects gzip representation; coding has not been applied yet.
- Browser / Duru
- Awaiting response
- Atlas selection and encoder
- text/plain + gzip selected
- Representation inventory
- Representation: Çay; 4 bytes
- Native gzip coding
Fixture gzip bytes occupy 24; decoded input occupies 4.
- Browser / Duru
- Awaiting response
- Atlas selection and encoder
- Gzip content: 24 bytes
- Representation inventory
- Representation: Çay; 4 bytes
- Framing and Vary
Content-Length: 24 without Transfer-Encoding; Vary identifies selection context.
- Browser / Duru
- Awaiting response
- Atlas selection and encoder
- 200 ready; CL=24
- Representation inventory
- Representation: Çay; 4 bytes
- Complete response arrived
Coded/framed bytes reached the receiver; decoded text is a separate step.
- Browser / Duru
- 24-byte gzip content received
- Atlas selection and encoder
- 200 ready; CL=24
- Representation inventory
- Representation: Çay; 4 bytes
- Decode and interpret
Decode the gzip content coding before interpreting UTF-8; decoded Çay is four bytes, a different measurement from Content-Length: 24.
- Browser / Duru
- Çay; decoded 4 bytes
- Atlas selection and encoder
- 200 ready; CL=24
- Representation inventory
- Representation: Çay; 4 bytes
Identity + chunks
- Preferences prepared
Media and coding preferences are distinct, not authentication evidence.
- Browser / Duru
- GET /tea-label ready; text/plain / identity; awaiting response
- Atlas selection and encoder
- No request
- Representation inventory
- Representation: Çay; 4 bytes
- GET arrived
The Application received Accept and Accept-Encoding without selecting a representation yet.
- Browser / Duru
- GET /tea-label ready; text/plain / identity; awaiting response
- Atlas selection and encoder
- Preferences received
- Representation inventory
- Representation: Çay; 4 bytes
- Variant selection
Select identity content; apply chunked framing separately.
- Browser / Duru
- Awaiting response
- Atlas selection and encoder
- text/plain + identity selected
- Representation inventory
- Representation: Çay; 4 bytes
- Framing and Vary
Valid chunks without Content-Length; Vary identifies selecting values.
- Browser / Duru
- Awaiting response
- Atlas selection and encoder
- 200 chunked ready; framed body 19 bytes
- Representation inventory
- Representation: Çay; 4 bytes
- Complete response arrived
Coded/framed bytes reached the receiver; decoded text is a separate step.
- Browser / Duru
- 19-byte chunked body received
- Atlas selection and encoder
- 200 chunked ready; framed body 19 bytes
- Representation inventory
- Representation: Çay; 4 bytes
- Decode and interpret
After removing chunked framing, interpret UTF-8 Çay as four bytes; the 19-byte framed total is not the representation size.
- Browser / Duru
- Çay; decoded 4 bytes
- Atlas selection and encoder
- 200 chunked ready; framed body 19 bytes
- Representation inventory
- Representation: Çay; 4 bytes
Strict policy: 406
- Preferences prepared
Media and coding preferences are distinct, not authentication evidence.
- Browser / Duru
- GET /tea-label ready; image/png / identity; awaiting response
- Atlas selection and encoder
- No request
- Representation inventory
- Representation: Çay; 4 bytes
- GET arrived
The Application received Accept and Accept-Encoding without selecting a representation yet.
- Browser / Duru
- GET /tea-label ready; image/png / identity; awaiting response
- Atlas selection and encoder
- Preferences received
- Representation inventory
- Representation: Çay; 4 bytes
- Variant selection
Strict policy selects 406 without a target representation.
- Browser / Duru
- Awaiting response
- Atlas selection and encoder
- 406 explanation selected
- Representation inventory
- Representation: Çay; 4 bytes
- Framing and Vary
Content-Length: 28 without Transfer-Encoding; Vary identifies selection context.
- Browser / Duru
- Awaiting response
- Atlas selection and encoder
- 406 ready; CL=28
- Representation inventory
- Representation: Çay; 4 bytes
- Complete response arrived
The Browser received the text/plain error explanation framed by Content-Length: 28. There is no Content-Encoding; the next local step interprets UTF-8 rather than decoding gzip.
- Browser / Duru
- 406 explanation received
- Atlas selection and encoder
- 406 ready; CL=28
- Representation inventory
- Representation: Çay; 4 bytes
- Decode and interpret
Read the text explanation without claiming an image target was selected.
- Browser / Duru
- 406: no acceptable target variant
- Atlas selection and encoder
- 406 ready; CL=28
- Representation inventory
- Representation: Çay; 4 bytes
ACTORS · STATE · DATA FLOW
Which bytes does Content-Length count?
Atlas returns Çay for GET /tea-label. UTF-8 identity representation has 3 code points and 4 bytes. Content-Length: 4 in HTTP/1.1 gives the expected content octet length, excluding start-line, headers, and separator bytes. A receiver must have the content octets required by framing before treating the message as complete.
With gzip content coding, Content-Length counts transferred gzip content rather than decoded Çay. This fixture was generated by native Node zlib gzipSync: 4-byte UTF-8 input produced 24 gzip bytes with level=9. That is a real local result for this tiny input, not a universal size or performance promise.
An HTTP/1.1 sender does not generate both Content-Length and Transfer-Encoding in one message. Absence of Content-Length does not make every message bodyless: direction, method/status, and version-specific framing matter together. HEAD metadata and 204 content restrictions retain their distinct rules from WEB-07.02.
Chunked discovers the content boundary incrementally
Transfer-Encoding: chunked carries HTTP/1.1 content in size-prefixed chunks. Sizes are hexadecimal octet counts, not character counts. This fixture has two valid chunks: Ç occupies 2 UTF-8 bytes and ay another 2. A zero-sized last chunk and empty trailer section finish it. Dechunking produces 4 content bytes; size lines and CRLF wrappers are not content.
The complete framed chunked body occupies 19 bytes: 4 content bytes plus 15 bytes of size/CRLF overhead. Dechunked content occupies 4. HTTP headers are also excluded from the 19-byte measure. The artifact provides both chunks and complete CRLF body notation. Static chunks teach the mechanism without simulating actual streaming timing or unknown-length generation.
Chunked is neither a content media type nor encryption. Transfer coding belongs to a particular HTTP/1.1 message transfer; content coding belongs to a representation. HTTP/2 and HTTP/3 prohibit Transfer-Encoding as connection-specific and use their own stream framing. The request TE: trailers exception does not permit Transfer-Encoding.
Content-Encoding changes bytes representing the same meaning
Content-Type: text/plain; charset=utf-8 describes decoded representation format. Content-Encoding: gzip declares the need to decode gzip first. This illustration obtains 24 coded bytes, removes gzip, then interprets 4 UTF-8 bytes. Layer order does not require buffering the whole body; a streaming implementation can apply it incrementally. A media parser cannot treat gzip bytes directly as Çay.
Gzip expands this tiny content from 4 to 24 bytes because format overhead outweighs savings. Compression decisions consider size, already-compressed formats, CPU cost, and cache variants. Level=9 is an explicit test parameter, not a production recommendation.
Header compression is separate: HTTP/2 HPACK and HTTP/3 QPACK encode header field blocks rather than gzip body content. A response can combine a negotiated gzip representation with appropriate version framing. Here gzip+Content-Length and identity+chunked are separate valid alternatives.
Preferences, selection, and cache reuse
Accept supplies media preferences; Accept-Encoding supplies content-coding preferences. Relative q weights express preference, with q=0 meaning unacceptable and omitted q meaning 1. Server selection uses available variants and policy. Preferences are neither permission lists nor a guaranteed response contract.
The normal fixture requests text/plain and ranks gzip above identity. The server deliberately chooses gzip for demonstration. The chunked branch requests identity, so the server applies no content coding while framing the HTTP/1.1 message as chunked. Content-coding preference is distinct from framing preference.
The strict branch sends Accept: image/png, but Atlas offers only text/plain and selects 406 under its explicit strict policy. HTTP can allow an origin to send a default representation rather than honor every preference; 406 is not mandatory for every mismatch. An error explanation is not the requested target’s selected image representation.
Vary: Accept, Accept-Encoding informs caches which request fields influenced representation selection. Reuse must match relevant selecting values or be validated by the origin. Vary neither grants resource permission nor defines every caching policy; personalized/private data need additional rules.
2. Red · Trust & Impact
Read every scenario without motion
Coded/decoded
- The length was assigned to its layer
When Çay is carried with gzip, coded content occupies 24 bytes and decoded UTF-8 content occupies 4. Content-Length declares the coded length of 24 in this response, not characters or decoded length.
- Content ledger
- gzip: coded 24 / decoded 4
- Framing/selection gate
- Layer check pending
- Reuse boundary
- No acceptance result
- Framing completeness used the right count
Comparing 4 decoded bytes with Content-Length 24 would misclassify the normal response as incomplete. The framing gate counts coded content; decoding is another stage. A small decoded result does not validate every processing limit.
- Content ledger
- gzip: coded 24 / decoded 4
- Framing/selection gate
- Content-Length = coded 24
- Reuse boundary
- No acceptance result
- Completeness was not promoted to permission
The ledger’s coded length is consistent. It establishes neither resource permission nor permission to share a cached response. Coded and decoded limits serve their own purposes; this four-byte example does not prove large-content behavior.
- Content ledger
- gzip: coded 24 / decoded 4
- Framing/selection gate
- Content-Length = coded 24
- Reuse boundary
- Length consistent / permission unknown
- The chunk wrapper produces another length
In the identity branch the content still occupies 4 bytes, while the valid chunk wrapper makes the body notation 19 bytes. The two chunk data lengths are 2 and 2. Calling wrapper overhead content or gzip coding confuses separate layers.
- Content ledger
- Identity: content 4 / chunked wire 19
- Framing/selection gate
- Content-Length = coded 24
- Reuse boundary
- Length consistent / permission unknown
- Transfer coding and content coding were separated
Transfer-Encoding: chunked establishes this HTTP/1.1 message boundary. Content-Encoding: gzip describes representation coding. The identity chunked branch has contentCoding null; equal text does not imply equal byte layouts.
- Content ledger
- Identity: content 4 / chunked wire 19
- Framing/selection gate
- Chunked H1 framing / contentCoding null
- Reuse boundary
- Length consistent / permission unknown
- The layer result retained its scope
The normal gzip and chunked branches reach the same Çay text. Correct checks compare each count at its own layer. This is not a complete HTTP-parser, browser-decoding or network-delivery measurement, nor an access-control decision.
- Content ledger
- Identity: content 4 / chunked wire 19
- Framing/selection gate
- Chunked H1 framing / contentCoding null
- Reuse boundary
- Separate coded/decoded/framing checks
Variant scope
- The same target carries two selection contexts
The old request accepts gzip;q=1, identity;q=0.5 while the new request asks for identity. Both address /tea-label. Equal target text does not make their Accept-Encoding values equal; selecting fields must be identified.
- Content ledger
- Old gzip / new identity
- Framing/selection gate
- Layer check pending
- Reuse boundary
- No acceptance result
- Vary matching bounded representation reuse
Vary includes Accept and Accept-Encoding. The changed coding preference therefore yields selectingValuesMatch false and cacheReuse false. Ignoring that dimension would apply the ledger’s reuse predicate incorrectly.
- Content ledger
- Old gzip / new identity
- Framing/selection gate
- selectingValuesMatch=false / cacheReuse=false
- Reuse boundary
- No acceptance result
- A reuse decision did not permit private sharing
The other row may yield cacheReuse true when selecting values match; originValidated remains false. This is only the selected matching calculation. Vary does not make private data public or replace recipient authorization.
- Content ledger
- Old gzip / new identity
- Framing/selection gate
- selectingValuesMatch=false / cacheReuse=false
- Reuse boundary
- Matching only / originValidated=false
- The media request was considered separately
The strict406 request asks for image/png, while the endpoint supports only text/plain. Its explicit strict policy produces 406 and No acceptable representation. That explanatory text is not a selected PNG representation.
- Content ledger
- Accept image/png / status 406
- Framing/selection gate
- selectingValuesMatch=false / cacheReuse=false
- Reuse boundary
- Matching only / originValidated=false
- The policy choice was not made universal
Here 406 follows the endpoint’s explicit selectionPolicy. Another origin may choose a default response. Recording media selection, content coding and framing separately identifies the condition behind an ordinary failure.
- Content ledger
- Accept image/png / status 406
- Framing/selection gate
- Explicit strict406 / other policies possible
- Reuse boundary
- Matching only / originValidated=false
- The representation check retained its boundary
The two reuse rows and strict406 result explain the selected representation predicates. No real cache store, cross-user delivery or origin revalidation was observed. Matching alone therefore cannot establish application confidentiality.
- Content ledger
- Accept image/png / status 406
- Framing/selection gate
- Explicit strict406 / other policies possible
- Reuse boundary
- Selection known / recipient policy separate
ASSUMPTION · BOUNDARY · CONTROL
Conflating two lengths creates an incorrect boundary
A normal coded response has Content-Length=24 while decoded text occupies 4 bytes. Comparing decoded size with transferred content size produces incorrect completeness or limit decisions. Chunk-wrapper overhead must also stay separate from content size; real stacks process these layers at different stages.
Use established HTTP-framing and compression libraries, with distinct coded/decoded limits and bounded processing. This lesson uses valid bounded bytes without conflicting headers, parser differentials, or malformed-chunk reproduction. Completion of tiny content cannot prove resource limits for large content.
Keep negotiated variants within the correct cache scope
One target can select different representations for acceptable coding or media contexts. An incorrect selecting-field inventory can contribute to incompatible cache reuse, with impact depending on the concrete cache and recipient. Client metadata such as Accept or User-Agent is not access-control evidence.
Review variant dimensions, Vary, cache directives, and output media metadata together. Vary: Accept-Encoding describes coding selection without making a private response publicly cacheable. This fixture has no cache store or cross-user serving; it includes only a reuse-matching predicate.
3. Blue · Secure development & defense
Read every scenario without motion
Byte ledger
- Hex and decoded text were retained together
gzip.codedHex identifies 24 coded bytes; decodedHex c3876179 is four UTF-8 bytes. Çay has three code points. These counts measure different things, so the diagnostic record must identify the measure it uses.
- Encoding record
- Coded 24 / decoded 4 / code points 3
- Evidence comparison
- Comparison pending
- Coverage verdict
- No verdict
- Decoder output matched its own byte count
Decoding the supplied gzip bytes should produce Çay and hex c3876179. A match can verify the local encoding/decoding calculation. Running a decoder does not separately establish HTTP framing, socket transfer or browser rendering.
- Encoding record
- Coded 24 / decoded 4 / code points 3
- Evidence comparison
- gzip decoded bytes match c3876179
- Coverage verdict
- No verdict
- Valid chunk data was separated from its wrapper
The first chunk carries the two bytes of Ç; the second carries the two bytes of ay. Size lines, CRLF and the final zero chunk make the notation 19 bytes. Removing the wrapper leaves four content bytes.
- Encoding record
- Chunks 2+2 / wire 19 / content 4
- Evidence comparison
- gzip decoded bytes match c3876179
- Coverage verdict
- No verdict
- The two representations were compared at content
Dechunked content and gunzip output yield the same c3876179 bytes. Gzip-coded content and chunked wire notation are not byte-for-byte equal. The comparison does not confuse equal text with equal complete messages.
- Encoding record
- Chunks 2+2 / wire 19 / content 4
- Evidence comparison
- Decoded content equal / encodings differ
- Coverage verdict
- No verdict
- Byte verification was not delivery evidence
The counts and content comparison are consistent for this small local fixture. There is no observation of network transfer, TLS, streaming performance or browser decoding. These are different evidence scopes, not byte-count failures.
- Encoding record
- Chunks 2+2 / wire 19 / content 4
- Evidence comparison
- Decoded content equal / encodings differ
- Coverage verdict
- Local bytes consistent / delivery unknown
- Regression rechecks the relevant layer
After a serialization change, coded and decoded counts must be recalculated; equal text does not preserve an old count. The check covers this valid bounded content and does not generalize to every parser input or production resource limit.
- Encoding record
- Chunks 2+2 / wire 19 / content 4
- Evidence comparison
- Decoded content equal / encodings differ
- Coverage verdict
- Recompute counts after serialization changes
Observation gap
- Selecting fields were selected for evidence
Reuse review needs old and new Accept and Accept-Encoding values together. The normal artifact provides them. If an observation lacks a selecting field, its absence proves neither equality nor inequality.
- Encoding record
- Required: old/new Accept and Accept-Encoding
- Evidence comparison
- Comparison pending
- Coverage verdict
- No verdict
- Normal and negative matches were separated
Complete rows yield reuse true for matching values and reuse false for changed Accept-Encoding. originValidated stays false. These normal results serve as contrasting controls, not measured cache-runtime events.
- Encoding record
- Required: old/new Accept and Accept-Encoding
- Evidence comparison
- Match→reuse true / mismatch→reuse false
- Coverage verdict
- No verdict
- The positive control demonstrated the oracle predicate
The selector’s separate positiveFixtureXml reports selectingValuesMatch false with cacheReuse true. XPath selects this inconsistent observation once. It tests the oracle, not a claim that a real cache served content to the wrong user.
- Encoding record
- Positive fixture: mismatch / reuse=true
- Evidence comparison
- Match→reuse true / mismatch→reuse false
- Coverage verdict
- No verdict
- Coverage was checked before interpreting zero matches
The normal XML yields zero matches; a missing observation can also yield zero. Treating both as equivalent without field coverage creates false confidence. The review gate separately checks whether the comparison’s required fields exist.
- Encoding record
- Positive fixture: mismatch / reuse=true
- Evidence comparison
- Zero matches / field coverage required
- Coverage verdict
- No verdict
- A missing field kept the outcome unknown
In this alternative review a required selecting field is unobserved. Copying the normal artifact’s complete row cannot fill that observation gap. Correct cache behavior remains UNKNOWN; missing data does not itself prove misuse.
- Encoding record
- Positive fixture: mismatch / reuse=true
- Evidence comparison
- Zero matches / field coverage required
- Coverage verdict
- UNKNOWN: selecting-field coverage
- A minimal field set was chosen for new evidence
The cache-selection component must correlate old and new Accept/Accept-Encoding values, Vary and the reuse decision for the same target. An absent request header can be a selecting value; failure to observe that header is an evidence gap. The verdict remains UNKNOWN until the record is available.
- Encoding record
- Positive fixture: mismatch / reuse=true
- Evidence comparison
- Zero matches / field coverage required
- Coverage verdict
- Needed: selecting values + decision + scope
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Compare content after removing the appropriate layers
In the manual exercise, distinguish gzip hex from decoded UTF-8 hex and match Content-Length to coded size. Match each chunk size with data bytes, then remove wrappers to recover the same Çay bytes. Equal text does not imply byte-for-byte equality of complete HTTP messages.
A gzip decoder can turn the supplied hex into c3876179, the UTF-8 bytes of Çay. Joining the data bytes of the two valid chunks leaves the same four bytes. Decoding and byte counts can establish this local transformation, not HTTP receipt, browser display or streaming performance.
Selecting values and missing evidence
Reuse rows compare two Accept-Encoding contexts: a stored gzip request and an identity request do not have matching selecting values when Vary includes that field. Compare actual old/new values for each field, including absence. Origin revalidation is supplied false in this example.
The XPath selects cacheReuse=true with selectingValuesMatch=false. Normal rows yield 0 and an inconsistent positive fixture yields 1. Missing observations can also yield 0 without proving correct cache behavior. Diagnostic evidence can record coding, byte counts, and selection reasons without logging entire sensitive content.
Configure the origin’s supported representations and content codings explicitly; do not advertise a format the origin cannot produce merely because a client requests it. This target selects media by Accept and coding by Accept-Encoding, so Vary declares both. Unconditionally reusing stored gzip for a new identity request loses that selection. Verify normal reuse with matching preferences alongside no reuse for a different encoding context; strict406 is this target’s chosen policy.
NOW APPLY IT TO THE CASE
Which different boundaries do gzip, the chunk wrapper and Vary control?
Çay has three code points and four UTF-8 bytes. Its gzip content occupies 24 bytes and valid chunked notation 19. When the coding preference changes for /tea-label, Vary matching must be reconsidered.
Evaluate the case’s 200, media type and parse-error records separately. Use representation rules to identify the remaining condition for usable data.
Open the related case file ↗READ THE EXAMPLE TOGETHER
Çay: gzip content and a valid chunked message
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"target": "/tea-label",
"gzip": {
"decodedText": "Çay",
"decodedCodePoints": 3,
"decodedOctets": 4,
"decodedHex": "c3876179",
"codedHex": "1f8b08000000000002133bdc9e5809008f00f9f404000000",
"codedOctets": 24,
"fixtureCompressionLevel": 9
},
"chunked": {
"chunks": [
{
"sizeHex": "2",
"dataText": "Ç",
"dataUtf8Hex": "c387",
"dataOctets": 2
},
{
"sizeHex": "2",
"dataText": "ay",
"dataUtf8Hex": "6179",
"dataOctets": 2
}
],
"lastChunkSizeHex": "0",
"trailerFields": [],
"bodyNotation": "2\r\nÇ\r\n2\r\nay\r\n0\r\n\r\n",
"bodyWireOctets": 19,
"dechunkedText": "Çay",
"dechunkedOctets": 4
},
"gzipResponseHead": "HTTP/1.1 200 OK\r\nDate: Thu, 08 Oct 2026 00:00:00 GMT\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Encoding: gzip\r\nContent-Length: 24\r\nVary: Accept, Accept-Encoding\r\n\r\n",
"chunkedResponseHttp11": "HTTP/1.1 200 OK\r\nDate: Thu, 08 Oct 2026 00:00:00 GMT\r\nContent-Type: text/plain; charset=utf-8\r\nTransfer-Encoding: chunked\r\nVary: Accept, Accept-Encoding\r\n\r\n2\r\nÇ\r\n2\r\nay\r\n0\r\n\r\n",
"variants": [
{
"case": "normal",
"requestHeaders": {
"Accept": "text/plain",
"Accept-Encoding": "gzip;q=1, identity;q=0.5"
},
"status": 200,
"selectedMediaType": "text/plain; charset=utf-8",
"contentCoding": "gzip",
"framing": "content-length",
"responseHeaders": {
"Content-Type": "text/plain; charset=utf-8",
"Content-Encoding": "gzip",
"Content-Length": "24",
"Vary": "Accept, Accept-Encoding"
},
"contentOctets": 24,
"decodedOctets": 4,
"browserDecodedText": "Çay"
},
{
"case": "chunked-identity",
"requestHeaders": {
"Accept": "text/plain",
"Accept-Encoding": "identity"
},
"status": 200,
"selectedMediaType": "text/plain; charset=utf-8",
"contentCoding": null,
"framing": "chunked",
"responseHeaders": {
"Content-Type": "text/plain; charset=utf-8",
"Transfer-Encoding": "chunked",
"Vary": "Accept, Accept-Encoding"
},
"contentOctets": 4,
"chunkedBodyWireOctets": 19,
"decodedOctets": 4,
"browserDecodedText": "Çay"
},
{
"case": "strict406",
"requestHeaders": {
"Accept": "image/png",
"Accept-Encoding": "identity"
},
"status": 406,
"selectedMediaType": null,
"contentCoding": null,
"framing": "content-length",
"responseHeaders": {
"Content-Type": "text/plain; charset=utf-8",
"Content-Length": "28",
"Vary": "Accept, Accept-Encoding"
},
"contentOctets": 28,
"decodedOctets": 28,
"browserDecodedText": "No acceptable representation",
"policy": "strict negotiated target selection; explanatory text is not a selected image representation"
}
],
"selectionPolicy": {
"supportedMediaTypes": [
"text/plain"
],
"supportedContentCodings": [
"gzip",
"identity"
],
"normalGzipChosenForDemonstration": true,
"unmatchedMedia": "explicit strict406; other origins may choose a default response"
},
"cacheReuseRows": [
{
"oldAccept": "text/plain",
"newAccept": "text/plain",
"oldAcceptEncoding": "gzip;q=1, identity;q=0.5",
"newAcceptEncoding": "gzip;q=1, identity;q=0.5",
"selectingValuesMatch": true,
"originValidated": false,
"cacheReuse": true
},
{
"oldAccept": "text/plain",
"newAccept": "text/plain",
"oldAcceptEncoding": "gzip;q=1, identity;q=0.5",
"newAcceptEncoding": "identity",
"selectingValuesMatch": false,
"originValidated": false,
"cacheReuse": false
}
],
"selector": {
"language": "XPath",
"xml": "<observations><reuse selectingValuesMatch=\"true\" cacheReuse=\"true\"/><reuse selectingValuesMatch=\"false\" cacheReuse=\"false\"/></observations>",
"xpath": "count(/observations/reuse[@selectingValuesMatch=\"false\" and @cacheReuse=\"true\"])",
"expected": 0,
"positiveFixtureXml": "<observations><reuse selectingValuesMatch=\"false\" cacheReuse=\"true\"/></observations>",
"positiveExpected": 1,
"scope": "Only authored protocol-decision observations, not product log field names or a live HTTP capture.",
"missingFieldBehavior": "Missing observation is insufficient evidence; zero matches is not proof of correct runtime behavior."
}
}- gzip.codedOctets / decodedOctets
- Native local gzip is 24 bytes, decoded UTF-8 4, excluding full HTTP-message overhead.
- chunked.bodyWireOctets
- Valid wrapper included: 19 bytes; dechunked content: 4 bytes.
- variants
- Explicit server selection, media, coding, and framing decisions.
- cacheReuseRows
- Only Vary selecting-value matching, not an actual cache store.
Native local gzip bytes were actually generated; HTTP/TLS/browser execution did not run. Chunks are bounded valid synthetic bytes. Levels and sizes are not production-tuning advice.
Two reality checks
A gzip response Content-Length is the decoded text length.
It counts transferred coded octets: this fixture decodes 24 gzip bytes into 4 UTF-8 bytes, and compression can expand a tiny body.
Every server must return 406 whenever Accept preferences cannot be met.
This fixture selects 406 under strict policy. Proactive negotiation can permit a default representation; Vary describes selection context without granting permission.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
Gzip content is 24 bytes; decoded Çay is 4 bytes. Which size does Content-Length specify?
- 24 coded octets in this response.
- 4; decompressed text length is always used.
Read the explained answer
24 coded octets in this response. — The gzip response head carries Content-Encoding:gzip and Content-Length:24; decoded length differs.
How do two sizeHex=2 chunks yield four content octets and nineteen body-wire octets?
Selected lesson artifact fields; teaching example
- chunked.chunks
- [{"sizeHex":"2","dataText":"Ç","dataUtf8Hex":"c387","dataOctets":2},{"sizeHex":"2","dataText":"ay","dataUtf8Hex":"6179","dataOctets":2}]
- chunked.bodyWireOctets
- 19
- chunked.dechunkedOctets
- 4
- There are nineteen application characters; chunk size counts code points.
- Chunk data totals four; size lines, separators and the terminator increase wire size.
Read the explained answer
Chunk data totals four; size lines, separators and the terminator increase wire size. — Ç is two UTF-8 octets and ay is two octets. Dechunking removes framing metadata.
An old cached request prefers gzip; a new request uses identity. Why does Vary change the reuse boundary?
Read the explained answer
The selected response carries Vary:Accept, Accept-Encoding. The changed selecting Accept-Encoding value prevents direct reuse of this stored representation. Vary does not make private data public; strict406 is also an origin policy, not mandatory behavior of every origin.
□ I linked representation selection to cache reuse.
□ I inferred no privacy guarantee from Vary.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- RFC 9110 — HTTP Semantics8.4 Content-Encoding · 8.6 Content-Length · 12.1 Proactive Negotiation · 12.4.2 Quality Values · 12.5.1 Accept · 12.5.3 Accept-Encoding · 12.5.5 Vary
- RFC 9112 — HTTP/1.16.1 Transfer-Encoding · 6.2 Content-Length · 6.3 Message Body Length · 7.1 Chunked Transfer Coding
- RFC 9113 — HTTP/28.2.2 Connection-Specific Header Fields · 4.3 Field Section Compression and Decompression · 4.3.1 Compression State
- RFC 9114 — HTTP/34.2 HTTP Fields · 4.2.1 Field Compression
- MDN — Content negotiationServer-driven content negotiation · The Accept header · The Vary response header