WEB / WEB-07.03
Headers, bodies, and media types
Message boundaries, byte decoding, and acceptance of decoded data are separate decisions. Follow them through a small request containing Çay.
1. Core · Mechanism
Read every scenario without motion
UTF-8 JSON: 200
- Serialized content ready
Prepare Duru’s benign content as UTF-8, keeping byte and code-point measures separate.
- Browser / Duru
- {"title":"Çay"}; 16 bytes; awaiting response
- Atlas Application
- No request
- Resource / local state
- Title: Draft
- Complete request arrived
Complete content matching Content-Length reached the Application; parsing and commit have not occurred.
- Browser / Duru
- {"title":"Çay"}; 16 bytes; awaiting response
- Atlas Application
- Complete 16 bytes; application/json
- Resource / local state
- Title: Draft
- Media policy
The endpoint accepts only application/json. This format is supported.
- Browser / Duru
- Awaiting response
- Atlas Application
- Media allowed; parsing pending
- Resource / local state
- Title: Draft
- JSON parsing
JSON syntax is valid and title parses as the string Çay; schema evaluation and record commit have not happened yet.
- Browser / Duru
- Awaiting response
- Atlas Application
- Parsed; title string
- Resource / local state
- Title: Draft
- Schema and action decision
String schema and supplied permission pass; commit the title.
- Browser / Duru
- Awaiting response
- Atlas Application
- Accepted
- Resource / local state
- Title: Çay
- Select the response format
Status 200 and text/plain result 4 bytes; response type is not copied from the request.
- Browser / Duru
- Awaiting response
- Atlas Application
- 200 ready; text/plain; 4 bytes
- Resource / local state
- Title: Çay
- Result arrived at the Browser
Response headers and content reached the browser; title state changed only in the accepted branch.
- Browser / Duru
- 200 received; Çay
- Atlas Application
- 200 ready; text/plain; 4 bytes
- Resource / local state
- Title: Çay
Media policy: 415
- Serialized content ready
Prepare Duru’s benign content as UTF-8, keeping byte and code-point measures separate.
- Browser / Duru
- {"title":"Çay"}; 16 bytes; awaiting response
- Atlas Application
- No request
- Resource / local state
- Title: Draft
- Complete request arrived
Complete content matching Content-Length reached the Application; parsing and commit have not occurred.
- Browser / Duru
- {"title":"Çay"}; 16 bytes; awaiting response
- Atlas Application
- Complete 16 bytes; text/plain
- Resource / local state
- Title: Draft
- Media policy
The endpoint accepts only application/json. text/plain is unsupported; parser is not invoked.
- Browser / Duru
- Awaiting response
- Atlas Application
- Media rejected; 415 selected
- Resource / local state
- Title: Draft
- Schema and writing skipped
Because media acceptance failed, the parser and schema are not run and no title write occurs. Draft is retained. This step is not the outcome of an unperformed schema check.
- Browser / Duru
- Awaiting response
- Atlas Application
- Rejected; no commit
- Resource / local state
- Title: Draft
- Select the response format
Status 415 and text/plain result 22 bytes; response type is not copied from the request.
- Browser / Duru
- Awaiting response
- Atlas Application
- 415 ready; text/plain; 22 bytes
- Resource / local state
- Title: Draft
- Result arrived at the Browser
Response headers and content reached the browser; title state changed only in the accepted branch.
- Browser / Duru
- 415 received; Unsupported media type
- Atlas Application
- 415 ready; text/plain; 22 bytes
- Resource / local state
- Title: Draft
Schema: 422
- Serialized content ready
Prepare Duru’s benign content as UTF-8, keeping byte and code-point measures separate.
- Browser / Duru
- {"title":123}; 13 bytes; awaiting response
- Atlas Application
- No request
- Resource / local state
- Title: Draft
- Complete request arrived
Complete content matching Content-Length reached the Application; parsing and commit have not occurred.
- Browser / Duru
- {"title":123}; 13 bytes; awaiting response
- Atlas Application
- Complete 13 bytes; application/json
- Resource / local state
- Title: Draft
- Media policy
The endpoint accepts only application/json. This format is supported.
- Browser / Duru
- Awaiting response
- Atlas Application
- Media allowed; parsing pending
- Resource / local state
- Title: Draft
- JSON parsing
Syntax is valid; title is number 123; syntax is still valid.
- Browser / Duru
- Awaiting response
- Atlas Application
- Parsed; title number
- Resource / local state
- Title: Draft
- Schema and action decision
The title field fails the required string schema; this fixture prepares 422 and leaves the existing record unchanged.
- Browser / Duru
- Awaiting response
- Atlas Application
- Rejected; no commit
- Resource / local state
- Title: Draft
- Select the response format
Status 422 and text/plain result 13 bytes; response type is not copied from the request.
- Browser / Duru
- Awaiting response
- Atlas Application
- 422 ready; text/plain; 13 bytes
- Resource / local state
- Title: Draft
- Result arrived at the Browser
Response headers and content reached the browser; title state changed only in the accepted branch.
- Browser / Duru
- 422 received; Invalid title
- Atlas Application
- 422 ready; text/plain; 13 bytes
- Resource / local state
- Title: Draft
ACTORS · STATE · DATA FLOW
A header is a field; values do not all combine the same way
HTTP fields carry name/value metadata. Field names are case-insensitive: Content-Type and content-type identify the same field. Value interpretation follows that field’s definition; lowercasing every value or joining every repeated field with commas is not a universal rule. Some fields use list syntax, others require a single value; Content-Type is a singleton.
In a request, Content-Type describes the submitted content format, while Accept describes response preferences. Response Content-Type describes what the server returns. One is not copied automatically into the other. Content-Length concerns content octets rather than business text length or media type.
Headers carry control/metadata, while content carries bytes for application processing. Trailer fields may also exist but are not arbitrary late equivalents of header fields. This fixture has none. A blank line ends the HTTP/1.1 header section; a separate framing rule determines the content boundary.
Request body: bytes → format → data → policy
Duru POSTs {"title":"Çay"} to /note-titles. Ç takes two bytes in UTF-8 serialization. The body has 15 Unicode code points but 16 bytes; Content-Length: 16 is calculated from UTF-8 body bytes. JavaScript string.length is not a general byte measure either: it counts UTF-16 code units. Headers and the blank separator are excluded from this length.
After receiving complete content, the Application applies allowed-media-type and supported-coding policy. The JSON parser produces a data structure for application/json. Schema then checks a string title, followed by product policy for this harmless action. A Content-Type: application/json declaration proves neither correct JSON syntax nor appropriate or authorized title data.
In the unsupported-media branch, the same JSON-looking bytes are declared text/plain. This endpoint accepts only application/json, so it chooses 415 without invoking its parser. In the schema branch, {"title":123} is valid JSON: parsing succeeds, but the string requirement fails and this API chooses 422. This is an example mapping, not a mandatory validation status for every JSON API.
A response body is not a mirror of the request
The normal action sets the title to Çay and returns Çay as its result. Although the request uses application/json, the response is Content-Type: text/plain; charset=utf-8. Its content has 3 code points and 4 bytes. Server response format and client processing must agree; response.json() is not the automatic continuation of every successful request.
A media type consists of type/subtype and defined parameters. For text/plain, charset=utf-8 declares text encoding. application/json, application/x-www-form-urlencoded, multipart/form-data, and application/octet-stream describe different formats or processing contexts; a file extension cannot reliably replace them. A multipart boundary separates parts and is distinct from HTTP message framing.
Serve response types correctly. Browsers may perform MIME sniffing in some contexts. nosniff affects specific Fetch checks, particularly script/style loading; it does not make every byte safe or replace server input validation and output-context protection. This lesson displays inert text without script evaluation or sniffing experiments.
Framing, content coding, and media format are separate layers
The HTTP/1.1 fixture announces content length using Content-Length and does not use Transfer-Encoding. Chunked transfer coding can delimit messages differently. A content coding such as Content-Encoding: gzip transforms representation data, while Content-Type describes the decoded representation format. With coding, Content-Length normally counts transferred coded octets, not characters in decompressed text.
Content-Type does not decide framing. An HTTP/1.1 sender must not generate both Content-Length and Transfer-Encoding. This lesson uses complete benign messages with one framing mechanism, without contradictory-framing examples or parser differentials. HTTP/2–3 do not reuse text CRLF/chunked framing; version-specific stream framing carries content.
Application policy extends beyond parsing: resource ownership, allowed action, size/depth limits, and persistence are additional decisions. The fixture assumes permissionAllows=true and tiny bounded content without implementing actual limits, authentication, or transactions. Message validity and business acceptance are different success conditions.
2. Red · Trust & Impact
Read every scenario without motion
Media gate
- The content label and business data were separated
unsupported-media has text/plain with a JSON-looking body. supportedRequestMediaTypes contains only application/json; appearance does not change the media contract.
- Content evidence
- text/plain / JSON-looking body
- Media/schema gate
- Acceptance decision pending
- Title-state boundary
- Title state Draft
- Gate reasons remain ordered and distinct
The message is complete, but the endpoint does not accept the request media type text/plain. The JSON parser is not called, so syntax and schema results remain null. No success or failure is invented for an unrun check.
- Content evidence
- text/plain / JSON-looking body
- Media/schema gate
- Media false / parser not called
- Title-state boundary
- Title state Draft
- The rejection branch changed no state
The rejected request leaves title state Draft and performs no commit. Supplied permission does not repair media or schema failure. Each required gate must meet its own predicate.
- Content evidence
- text/plain / JSON-looking body
- Media/schema gate
- Media false / parser not called
- Title-state boundary
- Draft unchanged / accepted=false
- Byte framing is not the media format
The normal title Çay body has 15 code points/16 UTF-8 bytes, while response Çay has 3/4. Content-Length counts bytes and Content-Type selects interpretation; they are different controls.
- Content evidence
- Length bytes / media interpretation separate
- Media/schema gate
- Media false / parser not called
- Title-state boundary
- Draft unchanged / accepted=false
- An error response has its own type
Media failure returns 415 Unsupported media type as text/plain. Rejection can be an ordinary contract outcome, not attacker attribution.
- Content evidence
- Length bytes / media interpretation separate
- Media/schema gate
- 415 / Unsupported media type
- Title-state boundary
- Draft unchanged / accepted=false
- The business boundary was preserved
Rejected requests do not change the title. The HTTP stack manages Content-Length; browser Fetch does not let script set that header. Retained Draft is supported by the application’s beforeTitle and afterTitle records.
- Content evidence
- Length bytes / media interpretation separate
- Media/schema gate
- 415 / Unsupported media type
- Title-state boundary
- Reject / Draft retained
Schema gate
- The content label and business data were separated
schema-rejected has application/json with title=123. JSON syntax can be valid while failing the required title-string schema.
- Content evidence
- application/json / numeric title
- Media/schema gate
- Acceptance decision pending
- Title-state boundary
- Title state Draft
- Gate reasons remain ordered and distinct
Message and media predicates pass, as does the JSON parser. The numeric title still fails the schema requiring a string. Parser success is neither business-schema nor permission success.
- Content evidence
- application/json / numeric title
- Media/schema gate
- Schema false / syntax true
- Title-state boundary
- Title state Draft
- The rejection branch changed no state
The rejected request leaves title state Draft and performs no commit. Supplied permission does not repair media or schema failure. Each required gate must meet its own predicate.
- Content evidence
- application/json / numeric title
- Media/schema gate
- Schema false / syntax true
- Title-state boundary
- Draft unchanged / accepted=false
- Byte framing is not the media format
The normal title Çay body has 15 code points/16 UTF-8 bytes, while response Çay has 3/4. Content-Length counts bytes and Content-Type selects interpretation; they are different controls.
- Content evidence
- Length bytes / media interpretation separate
- Media/schema gate
- Schema false / syntax true
- Title-state boundary
- Draft unchanged / accepted=false
- An error response has its own type
Schema failure returns 422 Invalid title as text/plain. A JSON request does not force the response into the same parser; response media is read separately.
- Content evidence
- Length bytes / media interpretation separate
- Media/schema gate
- 422 / Invalid title / text/plain
- Title-state boundary
- Draft unchanged / accepted=false
- The business boundary was preserved
Rejected requests do not change the title. The HTTP stack manages Content-Length; browser Fetch does not let script set that header. Retained Draft is supported by the application’s beforeTitle and afterTitle records.
- Content evidence
- Length bytes / media interpretation separate
- Media/schema gate
- 422 / Invalid title / text/plain
- Title-state boundary
- Reject / Draft retained
ASSUMPTION · BOUNDARY · CONTROL
A format label cannot serve as a trust decision
A client can select Content-Type; a normal endpoint uses it to select appropriate parsing and policy. Trusting that label while skipping schema or resource permissions can give data unintended business effects, depending on action and persistence scope. application/json does not make every field trusted.
Keep ordered boundaries explicit: complete content, supported media/coding, syntax parsing, schema, trusted action policy, then commit. Rejected branches must not commit. The media rejection and numeric title here are benign input errors rather than evidence of an attacker.
Protect byte boundaries and processing context together
Framing Unicode text by character count or comparing coded content with decoded length creates an incorrect completeness assumption. Copying response type from request type can also direct the client to the wrong parser. These confusions can undermine reliability and interpretation of trust boundaries.
Let an established HTTP stack handle serialization/framing and document application bytes, encoding, and parser contracts. Browser Fetch forbids scripts from setting some framing headers, so this raw text is not browser request-generation code. Defensive review distinguishes declared and observed format and ends mismatches with a safe error.
3. Blue · Secure development & defense
Read every scenario without motion
UTF-8 ledger
- Exact serialization bytes were selected
The request whose title is Çay has UTF-8 hex 7b227469746c65223a22c3876179227d and bodyOctets 16. Even a newline added during pretty-printing changes its length. A reformatted display cannot replace the captured bytes.
- Serialization evidence
- Request15 points /16 bytes
- Decision review
- No decision review
- State-effect review
- No state receipt
- Response encoding was calculated separately
Response Çay has3 code points/4 UTF-8 bytes and Content-Type text/plain; charset=utf-8. A JSON request does not imply a JSON response.
- Serialization evidence
- Request15 points /16 bytes
- Decision review
- Response3 points /4 bytes / text/plain
- State-effect review
- No state receipt
- Rejection reasons were read separately
The unsupported-media case returns 415 with parserCalled false. The schema-rejected case returns 422 with syntaxValid true and schemaValid false. These are different failure locations. The decision reason is retained without copying secrets or the entire body into audit.
- Serialization evidence
- Request15 points /16 bytes
- Decision review
- 415 media vs422 schema
- State-effect review
- No state receipt
- State-effect observation is independent
Rejected rows give beforeTitle=Draft, afterTitle=Draft. The normal accepted row changes Draft→Çay; both outcomes belong to policy regression.
- Serialization evidence
- Request15 points /16 bytes
- Decision review
- 415 media vs422 schema
- State-effect review
- Reject Draft→Draft / normal Draft→Çay
- An inconsistency predicate is not coverage
accepted=false, stateChanged=true is a supplied positive inconsistency fixture. Zero XPath matches can also come from missing observations; successful body/framing/schema enforcement is not inferred.
- Serialization evidence
- Predicate mismatch / missing coverage separate
- Decision review
- 415 media vs422 schema
- State-effect review
- Reject Draft→Draft / normal Draft→Çay
- Regression conclusions require their evidence
A UTF-8 serializer can produce byte counts and a JSON parser the syntax result. Media/schema decisions and beforeTitle/afterTitle belong to the application. Correlate them for the same /note-titles operation; HTTP status alone does not establish a title write.
- Serialization evidence
- Predicate mismatch / missing coverage separate
- Decision review
- 415 media vs422 schema
- State-effect review
- Serialization/decision/state consistent
State evidence gap
- Exact serialization bytes were selected
In this review the rejected row’s afterTitle observation is unavailable. beforeTitle=Draft and accepted=false are known; the complete example’s afterTitle cannot substitute for the missing record. First separate observed fields from unavailable ones.
- Serialization evidence
- beforeTitle Draft / afterTitle unobserved
- Decision review
- No decision review
- State-effect review
- No state receipt
- Response encoding was calculated separately
Response Çay has3 code points/4 UTF-8 bytes and Content-Type text/plain; charset=utf-8. A JSON request does not imply a JSON response.
- Serialization evidence
- Request15 points /16 bytes
- Decision review
- Response3 points /4 bytes / text/plain
- State-effect review
- No state receipt
- Rejection reasons were read separately
The unsupported-media case returns 415 with parserCalled false. The schema-rejected case returns 422 with syntaxValid true and schemaValid false. These are different failure locations. The decision reason is retained without copying secrets or the entire body into audit.
- Serialization evidence
- Request15 points /16 bytes
- Decision review
- 415 media vs422 schema
- State-effect review
- No state receipt
- State-effect observation is independent
This review branch supplies no afterTitle observation. accepted=false alone does not establish unchanged actual state; before/after evidence is required.
- Serialization evidence
- Request15 points /16 bytes
- Decision review
- 415 media vs422 schema
- State-effect review
- UNKNOWN: afterTitle
- An inconsistency predicate is not coverage
accepted=false, stateChanged=true is a supplied positive inconsistency fixture. Zero XPath matches can also come from missing observations; successful body/framing/schema enforcement is not inferred.
- Serialization evidence
- Predicate mismatch / missing coverage separate
- Decision review
- 415 media vs422 schema
- State-effect review
- UNKNOWN: afterTitle
- Regression conclusions require their evidence
UTF-8 and rejection-decision fields are known; actual state effects remain UNKNOWN. Completion requires state evidence from the same operation.
- Serialization evidence
- Predicate mismatch / missing coverage separate
- Decision review
- 415 media vs422 schema
- State-effect review
- Bytes known / state unknown
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Count bytes on the actual serialization
The artifact includes UTF-8 hex, Unicode code point count, and bodyOctets. Compare 15/16 for {"title":"Çay"} with 3/4 for response Çay. Even adding a pretty-print newline changes bytes; a reserialized view may differ from captured content length.
Count UTF-8 body bytes, match Content-Length, and independently read response media type. Then compare parser success with the schema branch’s commit decision. Local Python encoding and JSON parsing can verify these fixtures without constituting a full HTTP-parser, server, or browser test.
Check that rejected decisions leave state unchanged
Teaching observations pair accepted with stateChanged. The XPath selects accepted=false alongside stateChanged=true. Normal rows produce zero; a deliberately inconsistent positive fixture produces one. Missing observations indicate an evidence gap rather than correct controls; these are not claimed production log fields.
Real instrumentation should distinguish media rejection, syntax failure, and semantic validation failure without logging secrets or entire request bodies. Evaluate only necessary sanitized samples. Size and parser-resource limits depend on endpoint needs; the tiny fixture counts are not production-budget advice.
Bound request size before buffering or parsing, then check supported media type, parser result and the parsed object’s schema. Do not change Draft before this example’s string-title rule passes. Content-Type application/json does not establish a valid title: numeric title is syntactically JSON but remains in the 422 branch. Verify separately that 415 never calls the parser and 422 never changes storage, while preserving the normal Çay update after the checks pass.
NOW APPLY IT TO THE CASE
At which separate gates do media, syntax, schema and state effects arise?
The request aims to change a note title to Çay. Its JSON body occupies 16 UTF-8 bytes. Unsupported media produces 415 and a numeric title produces 422, both retaining Draft. The 4-byte text/plain response is interpreted separately from the request parser.
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 serialization: bytes, media, and decision
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"requestHttp11": "POST /note-titles HTTP/1.1\r\nHost: library.atlas.example\r\nContent-Type: application/json\r\nContent-Length: 16\r\n\r\n{\"title\":\"Çay\"}",
"responseHttp11": "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-Length: 4\r\n\r\nÇay",
"encoding": "UTF-8",
"dateIsSynthetic": true,
"contentEncoding": null,
"transferEncoding": null,
"supportedRequestMediaTypes": [
"application/json"
],
"schema": {
"type": "object",
"required": [
"title"
],
"properties": {
"title": {
"type": "string"
}
}
},
"rows": [
{
"case": "normal",
"requestContentType": "application/json",
"requestBody": "{\"title\":\"Çay\"}",
"requestCodePoints": 15,
"requestBodyOctets": 16,
"requestContentLengthField": 16,
"requestUtf8Hex": "7b227469746c65223a22c3876179227d",
"messageComplete": true,
"mediaAllowed": true,
"parserCalled": true,
"syntaxValid": true,
"schemaValid": true,
"permissionAllows": true,
"accepted": true,
"beforeTitle": "Draft",
"afterTitle": "Çay",
"status": 200,
"responseContentType": "text/plain; charset=utf-8",
"responseBody": "Çay",
"responseCodePoints": 3,
"responseBodyOctets": 4,
"responseContentLengthField": 4
},
{
"case": "unsupported-media",
"requestContentType": "text/plain",
"requestBody": "{\"title\":\"Çay\"}",
"requestCodePoints": 15,
"requestBodyOctets": 16,
"requestContentLengthField": 16,
"requestUtf8Hex": "7b227469746c65223a22c3876179227d",
"messageComplete": true,
"mediaAllowed": false,
"parserCalled": false,
"syntaxValid": null,
"schemaValid": null,
"permissionAllows": true,
"accepted": false,
"beforeTitle": "Draft",
"afterTitle": "Draft",
"status": 415,
"responseContentType": "text/plain; charset=utf-8",
"responseBody": "Unsupported media type",
"responseCodePoints": 22,
"responseBodyOctets": 22,
"responseContentLengthField": 22
},
{
"case": "schema-rejected",
"requestContentType": "application/json",
"requestBody": "{\"title\":123}",
"requestCodePoints": 13,
"requestBodyOctets": 13,
"requestContentLengthField": 13,
"requestUtf8Hex": "7b227469746c65223a3132337d",
"messageComplete": true,
"mediaAllowed": true,
"parserCalled": true,
"syntaxValid": true,
"schemaValid": false,
"permissionAllows": true,
"accepted": false,
"beforeTitle": "Draft",
"afterTitle": "Draft",
"status": 422,
"responseContentType": "text/plain; charset=utf-8",
"responseBody": "Invalid title",
"responseCodePoints": 13,
"responseBodyOctets": 13,
"responseContentLengthField": 13
}
],
"selector": {
"language": "XPath",
"xml": "<observations><decision accepted=\"true\" stateChanged=\"true\"/><decision accepted=\"false\" stateChanged=\"false\"/></observations>",
"xpath": "count(/observations/decision[@accepted=\"false\" and @stateChanged=\"true\"])",
"expected": 0,
"positiveFixtureXml": "<observations><decision accepted=\"false\" stateChanged=\"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."
}
}- requestBodyOctets / requestCodePoints
- UTF-8 bytes and Unicode code points are different measures: 16/15 in the fixture.
- parserCalled / schemaValid
- Supported format is separate from syntax parsing and schema evaluation.
- responseContentType
- The response can be text/plain despite an application/json request.
- afterTitle
- Commit only after acceptance gates pass; both rejections retain Draft.
- requestUtf8Hex
- Inert UTF-8 body-byte representation, not parser or execution instructions.
Original benign text and valid JSON fixtures without contradictory framing or executable payloads. Permission is supplied; local parser/count checks do not test an HTTP service, browser Fetch, or production limits.
Two reality checks
Content-Length is the number of characters in the JSON.
It counts serialized content octets. This UTF-8 body has 15 code points and 16 bytes, excluding headers.
An application/json request is valid and its response must also be JSON.
A media declaration proves neither syntax, schema, nor permission. The response format is selected separately; this normal fixture returns text/plain.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
JSON syntax is valid but title is a number. Does the schema-rejected branch change state?
- Yes; parsable JSON is automatically business-valid.
- No; 422 and Draft→Draft.
Read the explained answer
No; 422 and Draft→Draft. — syntaxValid=true and schemaValid=false; the selected handler does not write a title from rejected input.
Why is Content-Length 4 although Çay contains three code points?
Selected lesson artifact fields; teaching example
- rows[0].responseBody
- Çay
- rows[0].responseCodePoints
- 3
- rows[0].responseBodyOctets
- 4
- Ç uses two UTF-8 octets; a and y use one each.
- The length is wrong; every Unicode character always uses one byte.
Read the explained answer
Ç uses two UTF-8 octets; a and y use one each. — The selected uncompressed content is 2+1+1=4 bytes; framing length is not a code-point count.
A JSON-looking body is supplied with Content-Type text/plain. Why does the selected handler return 415 before calling the parser?
Read the explained answer
The selected endpoint accepts only application/json. Even with messageComplete, mediaAllowed=false leaves parserCalled=false; schema outcome is null and state stays Draft. This describes the endpoint contract, not generic server behavior.
□ I separated media and parser gates.
□ I stated that the rejected branch performs no mutation.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- RFC 9110 — HTTP Semantics5.1 Field Names · 5.2 Field Lines and Combined Field Value · 6.4 Content · 8.3 Content-Type · 8.4 Content-Encoding · 8.6 Content-Length · 15.5.16 415 Unsupported Media Type · 15.5.21 422 Unprocessable Content
- RFC 9112 — HTTP/1.12.1 Message Format · 6.2 Content-Length · 6.3 Message Body Length
- MDN — Content-Type headerContent-Type header · Syntax · Directives
- MDN — Media types (MIME types)Structure of a MIME type · MIME sniffing
- WHATWG — Fetch Standard (official source)X-Content-Type-Options header: destination-specific nosniff algorithm · Forbidden request-header: Content-Length and Transfer-Encoding
- OWASP — Input Validation Cheat SheetImplementing Input Validation: Parse Safely, Then Validate · Validate Structured Data