WEB / WEB-08.01
HTTP/1.x connections and framing
Track message boundaries and response order separately on one TCP byte stream. Persistence permits another exchange; pipelining does not interleave responses.
1. Core · Mechanism
Read every scenario without motion
Pipeline order
- Two GETs ready
The client chooses two safe GETs on one open connection without awaiting the first response.
- Client / Duru
- GET A /atlas-notes and B /tea ready; awaiting responses
- Atlas server
- No requests
- Local connection state
- conn-h1 open
- Request A arrived
The server receives the first complete GET as A; no response or status has reached the client.
- Client / Duru
- GET A /atlas-notes and B /tea ready; awaiting responses
- Atlas server
- A received
- Local connection state
- conn-h1 open
- Request B arrived
B arrives without waiting for A’s response, establishing receive order A followed by B.
- Client / Duru
- GET A /atlas-notes and B /tea ready; awaiting responses
- Atlas server
- A/B received
- Local connection state
- conn-h1 open
- B ready, A pending
Local scheduling prepares B first, but response-order rules keep it queued behind A.
- Client / Duru
- No response yet
- Atlas server
- B ready; A pending
- Local connection state
- Prepared order: B
- A also ready
A is also prepared. The server must follow received-request order, not preparation order: A with ten content bytes precedes B with four.
- Client / Duru
- No response yet
- Atlas server
- A CL10 and B CL4 ready; A first
- Local connection state
- Prepared order: B,A
- Response A arrived
The first complete response contains 10 content bytes, completing A before parsing B’s boundary.
- Client / Duru
- A complete: Atlas note
- Atlas server
- A delivered; B ready
- Local connection state
- conn-h1 open
- Response B arrived
The second complete response carries four UTF-8 bytes for Çay, preserving arrival order A then B.
- Client / Duru
- A/B complete; B: Çay
- Atlas server
- A/B delivered
- Local connection state
- conn-h1 open
- Ready for reuse
Both self-delimited bodies have been consumed; absent closure the connection can carry another exchange.
- Client / Duru
- Both complete
- Atlas server
- No pending response
- Local connection state
- conn-h1 reusable
HTTP/1.0 EOF
- Historical GET
The historical branch starts with one GET on a new HTTP/1.0 connection without persistence extensions.
- Client / Duru
- GET /tea ready; awaiting response
- Atlas server
- No request
- Local connection state
- conn-10 open
- GET arrived
The server receives the complete HTTP/1.0 request; its response body needs a separate boundary rule.
- Client / Duru
- GET /tea ready; awaiting response
- Atlas server
- GET /tea received
- Local connection state
- conn-10 open
- Close-delimited ready
The server prepares a valid response without Content-Length, relying on closure to delimit its body.
- Client / Duru
- Awaiting response
- Atlas server
- 200 ready; no CL
- Local connection state
- conn-10 open
- Bytes arrived
Status and four content bytes arrive, but without EOF the client cannot yet mark the message complete.
- Client / Duru
- 200; 4 bytes; incomplete
- Atlas server
- Response bytes delivered
- Local connection state
- conn-10 open
- Close event
A supplied transport closure updates local state without inventing logout traffic or another HTTP response.
- Client / Duru
- 200; 4 bytes; incomplete
- Atlas server
- Response bytes delivered
- Local connection state
- conn-10 closed; EOF
- EOF boundary
The client uses EOF to end the body: Çay is complete, while this connection can no longer be reused.
- Client / Duru
- Complete: Çay
- Atlas server
- Exchange finished
- Local connection state
- conn-10 not reusable
ACTORS · STATE · DATA FLOW
HTTP/1.0 as a historical baseline
When Duru’s Atlas client retrieves a note, HTTP/1.0 still carries a method, target, status, and representation metadata. RFC 1945 is an Informational document from May 1996, used here to explain historical behavior rather than define current HTTP/1.1 parser requirements.
Its ordinary operation opens a connection for each request and closes it after the response. Later keep-alive extensions are distinct from that baseline; equal persistence support cannot be assumed across HTTP/1.0 clients.
The historical fixture retrieves /tea using a 200 response without Content-Length. Çay occupies four UTF-8 bytes, but receipt of those bytes alone cannot establish that no more will follow. Supplied connection closure establishes the response-body boundary. Closing a request body is different because the server still needs to send its response.
A byte stream is not a message boundary
TCP delivers ordered bytes, but a socket read need not equal an HTTP message. One read can contain half a header, one message, or several messages together. HTTP/1.1 determines framing from the start-line, CRLF-delimited fields, blank separator, and method/status context.
The normal fixture concatenates two GET requests and two Content-Length responses. Atlas note occupies 10 content bytes and Çay occupies 4. After the first header section, a parser consumes exactly 10 content bytes; the next response start is not part of that content. Readable headers do not turn byte lengths into character counts.
HEAD/204 content restrictions, valid chunked framing, and close-delimited responses have distinct rules. This fixture uses only ordinary GET with one Content-Length per response. Current HTTP favors self-delimited responses because close delimiting makes normal completion harder to distinguish from transport failure.
Persistence permits reuse after completion
HTTP/1.1 can keep a connection persistent by default. The normal branch carries two exchanges on conn-h1 and leaves it open after both responses complete. Adding Keep-Alive is not a prerequisite for this default. Explicit close, peer policy, or transport events can end reuse.
The prior body must be consumed before reuse so its bytes are not mistaken for another message. A self-defined length supports an open connection. In contrast, a response whose body ends only at EOF consumes that connection’s ability to serve a later exchange.
An open connection proves neither an active application session nor a verified subject. Conn-h1 denotes a transport resource rather than an authentication record. The session/connection distinction from WEB-07.05 now connects to message completion and reuse, while policy decisions remain independent.
Pipelining retains response order
A client can send its second request without waiting for the first response: pipelining. Responses on that byte stream must follow received-request order. Safe requests can be processed in parallel, but their content cannot be arbitrarily interleaved without stream identifiers.
The scene receives A=/atlas-notes before B=/tea. B’s four-byte response is prepared first, but it waits while A is still preparing. Once A is ready, A’s response arrives before B’s. Prepared at the server and complete at the client are separate states: this is application-level head-of-line blocking.
Both requests are safe GETs, and the server delay is a supplied condition rather than a measured duration. Real clients need not use pipelining. Retry decisions depend on unanswered exchanges, method semantics, and partial failures; waiting or losing a connection does not prove a non-idempotent action never ran.
2. Red · Trust & Impact
Read every scenario without motion
Pipeline order
- Request order was marked with aliases
A names GET /atlas-notes and B names GET /tea. Their request order on the same HTTP/1.1 connection is A, B. The aliases provide teaching correlation, not actual HTTP/1.1 stream-identifier fields.
- Request/response ledger
- Requests: A, B
- Order/completion gate
- Completion gate pending
- Application boundary
- Delivery outcome unknown
- Preparation order was separated from delivery order
The server may prepare response B before A; preparedOrder is B, A. Pipeline response order remains A, B. Being ready does not allow B to move ahead of A for delivery to the client.
- Request/response ledger
- Requests: A, B
- Order/completion gate
- Prepared B,A / required delivery A,B
- Application boundary
- Delivery outcome unknown
- Waiting was not promoted to a forbidden result
B waits because of response ordering in this ledger. No authorization denial for B was observed. Two safe GETs on one connection likewise do not grant permission to both resources; application policy is another boundary.
- Request/response ledger
- Requests: A, B
- Order/completion gate
- Prepared B,A / required delivery A,B
- Application boundary
- B waits for order / permission unknown
- A socket read was not treated as a message boundary
The response stream carries A and B messages consecutively. TCP read groupings need not preserve those message boundaries. A’s Content-Length 10 identifies its content boundary; subsequent bytes may belong to the separate B message.
- Request/response ledger
- A content 10 / next bytes may be B
- Order/completion gate
- Prepared B,A / required delivery A,B
- Application boundary
- B waits for order / permission unknown
- Parser completion and bounded work were kept separate
A maintained parser completes each message under its framing rule instead of treating a read() return as a complete HTTP response. Pending work and timeouts are bounded separately. Here B waits for order; this is not a production-performance diagnosis.
- Request/response ledger
- A content 10 / next bytes may be B
- Order/completion gate
- Framing per message / bounded pending work
- Application boundary
- B waits for order / permission unknown
- The boundary result retained its evidence scope
deliveredOrder is supplied as A, B; the connection remains open after both contents complete. This record explains transport/message scheduling. It does not establish browser-pool, proxy, TLS or business-commit behavior.
- Request/response ledger
- A content 10 / next bytes may be B
- Order/completion gate
- Framing per message / bounded pending work
- Application boundary
- Order A,B / connection open / app unknown
EOF boundary
- Historical response framing was selected
The HTTP/1.0 /tea response has neither Content-Length nor Transfer-Encoding. Its Çay body occupies 4 bytes. This valid historical example completes at response connection close; seeing the body text alone does not identify the boundary.
- Request/response ledger
- H1.0 / CL absent / TE absent / body 4
- Order/completion gate
- Completion gate pending
- Application boundary
- Delivery outcome unknown
- Completion was not declared merely after body bytes
With four bytes present, completeBeforeClose is false. Close-delimited framing learns that no more body bytes follow from the close event. Starting to display the text does not establish HTTP-message completion.
- Request/response ledger
- H1.0 / CL absent / TE absent / body 4
- Order/completion gate
- Before close: complete=false
- Application boundary
- Delivery outcome unknown
- Incomplete state was not labeled application failure
At this stage parser completion is pending. No HTTP failure, authorization denial or session logout is added; those mechanisms need separate evidence. Partial content and a final outcome are not the same state.
- Request/response ledger
- H1.0 / CL absent / TE absent / body 4
- Order/completion gate
- Before close: complete=false
- Application boundary
- Completion pending / application unknown
- The supplied nature of the close event was retained
The historical ledger supplies a close event. It is not a native HTTP/1.0 socket measurement. After that event the parser knows the EOF boundary; the model invents neither another network packet nor a user logout.
- Request/response ledger
- Supplied close / not a socket measurement
- Order/completion gate
- Before close: complete=false
- Application boundary
- Completion pending / application unknown
- Completion and connection reuse reached different outcomes
completeAfterSuppliedClose becomes true and reusableAfterClose is false. The body is complete, but a new exchange cannot use the same closed connection. Copying the self-delimited HTTP/1.1 branch’s open result into this case would be incorrect.
- Request/response ledger
- Supplied close / not a socket measurement
- Order/completion gate
- After close: complete=true / reusable=false
- Application boundary
- Completion pending / application unknown
- Transport closure produced no session verdict
This EOF determines the HTTP body boundary and ends connection reuse. It supplies no evidence about a business operation, resource lifetime or session termination. Reaching the same Çay text does not make all protocol branches equivalent.
- Request/response ledger
- Supplied close / not a socket measurement
- Order/completion gate
- After close: complete=true / reusable=false
- Application boundary
- Message complete / session outcome unknown
ASSUMPTION · BOUNDARY · CONTROL
A wrong boundary produces a wrong exchange interpretation
Treating a socket read as a complete message can fail under normal fragmentation or coalescing. The condition is conflating TCP delivery units with HTTP framing; impact can include associating a response with the wrong resource.
Use maintained protocol parsers, version-aware completeness, and bounded buffering. Keep declared message length, received content bytes, and remaining bytes distinct. These two valid responses demonstrate that distinction without proving a parser safe for every input or deployment.
Starting to display content does not by itself establish a final business outcome or complete response. Separating partial observations from the completed exchange ledger gives security and incident analysis the correct boundary.
Queues and authorization consume different resources
B waits here because A must precede it, not because B is forbidden. Connections and pending responses consume resources, but every delay is not hostile: upstream delay, application work, and ordinary scheduling can expose similar wait states.
Bound pending work and apply explicit timeout/reuse policies separately from resource authorization. More connections can sometimes reduce response-order delays, but unlimited connections are not a general solution because server and network resources are shared.
Duru’s two GETs on one connection do not automatically permit both resources. A safe method is not an access-control result. This fixture teaches message scheduling while subject and resource policies belong at the real application boundary.
3. Blue · Secure development & defense
Read every scenario without motion
Message ledger
- Content count was separated from complete-message count
A’s Atlas note content is 10 bytes and its full response message is 127. B’s Çay content is 4 bytes and its full message is 120. Adding header and delimiter overhead to Content-Length would make the comparison incorrect.
- Message record
- A: 10/127 bytes / B: 4/120 bytes
- Correlation review
- Count/order review pending
- Evidence conclusion
- No coverage verdict
- UTF-8 accounting preserved the message boundary
Çay contains three code points but four UTF-8 bytes. B’s Content-Length 4 matches that content. Substituting character count for octet count would end the boundary at the wrong point in A/B correlation.
- Message record
- A: 10/127 bytes / B: 4/120 bytes
- Correlation review
- A CL 10 / B CL 4 consistent
- Evidence conclusion
- No coverage verdict
- Preparation and arrival arrays were read separately
preparedOrder is B, A while deliveredOrder is A, B. B-ready is not B-arrived. Keeping these measures separate for the same request order prevents ordinary pipeline waiting from being misclassified as wrong response order.
- Message record
- Prepared B,A / delivered A,B
- Correlation review
- A CL 10 / B CL 4 consistent
- Evidence conclusion
- No coverage verdict
- The order oracle used normal and positive controls
Normal selector XML has requestOrder A,B and deliveredOrder A,B, yielding zero mismatches. The positive XML reports deliveredOrder B,A and yields one. The positive control is an authored observation, not a recorded real protocol failure.
- Message record
- Prepared B,A / delivered A,B
- Correlation review
- Normal mismatch 0 / positive mismatch 1
- Evidence conclusion
- No coverage verdict
- Normal completion was not treated as a session event
After both self-delimited responses complete, connectionAfterComplete remains open. That is a connection-reuse condition. The message ledger contains no login, logout, user-role or private-resource-policy event.
- Message record
- Prepared B,A / delivered A,B
- Correlation review
- Normal mismatch 0 / positive mismatch 1
- Evidence conclusion
- Messages complete / connection open
- Regression was tied to byte and order predicates
Server preparation records can supply preparedOrder=B,A; the client HTTP parser can supply deliveredOrder=A,B and complete-message boundaries correlated with request order on the same connection. A/B are not stream IDs. Header serialization changes require recalculating message counts 127 and 120.
- Message record
- Prepared B,A / delivered A,B
- Correlation review
- Normal mismatch 0 / positive mismatch 1
- Evidence conclusion
- Recheck content bytes, message bytes and order
Arrival gap
- The observation scope was identified for review
In the alternative review, request order A,B and server preparation order are known, but client-delivery observations are missing. The normal artifact contains deliveredOrder; that value cannot be treated as evidence from the incomplete trace.
- Message record
- Request/preparation known / arrival unobserved
- Correlation review
- Count/order review pending
- Evidence conclusion
- No coverage verdict
- Preparation records did not close the arrival gap
B being ready first does not mean it arrived first. A’s ready record is not client receipt either. The correlation gate checks observer location and complete-message boundaries rather than replacing client measurements with server state.
- Message record
- Request/preparation known / arrival unobserved
- Correlation review
- Ready ≠ arrival / receiver coverage needed
- Evidence conclusion
- No coverage verdict
- A missing trace can produce zero matches
The order selector operates only on available pipeline observations. If delivered-order records are absent, the inconsistency count may remain zero. That does not establish trace completeness or preservation of protocol order.
- Message record
- Zero mismatch possible with missing evidence
- Correlation review
- Ready ≠ arrival / receiver coverage needed
- Evidence conclusion
- No coverage verdict
- The negative control was evaluated within scope
The complete normal XML and positive mismatch XML test oracle behavior together. Missing client observation is a different condition from either control. Substituting the fixture’s expected array for a missing observation would remove the coverage requirement.
- Message record
- Zero mismatch possible with missing evidence
- Correlation review
- Controls known / actual arrival evidence absent
- Evidence conclusion
- No coverage verdict
- The delivery verdict was left unknown
Delivery order remains UNKNOWN in this review. No network-loss, authorization-denial or session-termination conclusion is added. Missing evidence alone establishes neither success nor failure of the boundary.
- Message record
- Zero mismatch possible with missing evidence
- Correlation review
- Controls known / actual arrival evidence absent
- Evidence conclusion
- UNKNOWN: client delivery order
- New observation was scoped to the minimum need
A changed verdict requires client-observer records of message completion and correlation. Storing all private content is unnecessary; request order, declared length, completion and observer scope may suffice. The normal fixture’s result is not transferred without new evidence.
- Message record
- Zero mismatch possible with missing evidence
- Correlation review
- Controls known / actual arrival evidence absent
- Evidence conclusion
- Needed: receiver completion + correlation
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Record order and completeness in one ledger
Assign instructional A/B order aliases to requests and count response content bytes against declared lengths. These aliases are not HTTP/1.1 stream identifiers; correlation uses request order. Mark the next message starting after each response’s final byte.
B-ready can precede A-ready while B-arrived must follow A-arrived. Separate artifact arrays record preparation and delivery orders. The XPath selects an authored observation claiming reversed response delivery; normal and inconsistent fixtures return 0 and 1.
Missing observations can also return 0 without verifying ordering. Defer speed/success conclusions until trace scope, correlation, and completeness are established. Diagnostics need not retain entire bodies or personal notes.
Interpret closure in framing context
In the historical branch, receiving four content bytes does not yet end an EOF-delimited response. The supplied closure establishes its boundary and removes connection reuse. Drawing closure as application logout or resource deletion would invent another mechanism.
The current self-delimited branch completes CL=10 and CL=4 while leaving its connection open. Equal visible text does not imply equal completeness or reuse rules. Manual analysis proceeds from version/method/status through framing to transport closure.
A native local fixture can exercise in-order delivery for two safe GETs, while the authored scene as a whole remains a teaching model. Browser pooling, TLS, proxy conversion, production timeouts, and session policy require separate evidence.
An HTTP/1.1 client must consume the complete response body before reusing its connection for another request. A server must likewise consume the request body or close after responding. Leave framing to a standard HTTP implementation instead of treating an application read chunk as a whole message. For these two normal GETs, B must not be emitted before A even when ready earlier; ordered responses and completed body boundaries are distinct requirements to preserve together.
NOW APPLY IT TO THE CASE
What separate evidence do preparation, message completion and client arrival require?
A names the Atlas note response and B the Çay response. Even when the server prepares B first, HTTP/1.1 pipeline response order stays A, B. In the historical HTTP/1.0 example, four body bytes are insufficient; a close event identifies completion.
Which application conditions would remain if the case used another HTTP transport? Do not equate stream or packet completion with successful note parsing.
Open the related case file ↗READ THE EXAMPLE TOGETHER
A/B pipeline and EOF ledger
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"requests": [
{
"alias": "A",
"path": "/atlas-notes",
"wire": "GET /atlas-notes HTTP/1.1\r\nHost: library.atlas.example\r\n\r\n"
},
{
"alias": "B",
"path": "/tea",
"wire": "GET /tea HTTP/1.1\r\nHost: library.atlas.example\r\n\r\n"
}
],
"responses": [
{
"alias": "A",
"body": "Atlas note",
"contentOctets": 10,
"wire": "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: 10\r\n\r\nAtlas note",
"messageOctets": 127
},
{
"alias": "B",
"body": "Çay",
"contentOctets": 4,
"wire": "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",
"messageOctets": 120
}
],
"requestStream": "GET /atlas-notes HTTP/1.1\r\nHost: library.atlas.example\r\n\r\nGET /tea HTTP/1.1\r\nHost: library.atlas.example\r\n\r\n",
"responseStream": "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: 10\r\n\r\nAtlas noteHTTP/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",
"preparedOrder": [
"B",
"A"
],
"deliveredOrder": [
"A",
"B"
],
"connectionAfterComplete": "open",
"http10": {
"request": "GET /tea HTTP/1.0\r\n\r\n",
"responseBytesBeforeClose": "HTTP/1.0 200 OK\r\nDate: Thu, 08 Oct 2026 00:00:00 GMT\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nÇay",
"body": "Çay",
"bodyOctets": 4,
"contentLengthField": null,
"transferEncodingField": null,
"completionRule": "response connection close",
"completeBeforeClose": false,
"completeAfterSuppliedClose": true,
"reusableAfterClose": false,
"scope": "Historical valid close-delimited response; EOF event supplied, not a native HTTP1.0 measurement."
},
"selector": {
"language": "XPath",
"xml": "<observations><pipeline requestOrder=\"A,B\" deliveredOrder=\"A,B\"/></observations>",
"xpath": "count(/observations/pipeline[@requestOrder=\"A,B\" and @deliveredOrder!=\"A,B\"])",
"expected": 0,
"positiveFixtureXml": "<observations><pipeline requestOrder=\"A,B\" deliveredOrder=\"B,A\"/></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."
}
}- preparedOrder / deliveredOrder
- Server preparation and client arrival are distinct orders.
- contentOctets / messageOctets
- Content-Length counts content; the full message also contains headers.
- http10.completeBeforeClose
- EOF-delimited completeness is false before the supplied close.
Valid safe GET fixtures; A/B are not protocol fields. Historical close is supplied; native local pipeline evidence has a separate scope. Browser/TLS/proxy/session behavior is not measured.
Two reality checks
Pipelining interleaves the second response as soon as it is ready.
HTTP/1.1 response order follows request order. B waits for A even when prepared first; stream multiplexing is different.
An HTTP message ends whenever a TCP read ends.
Socket-delivery boundaries are not message boundaries. Self-delimited length or the correct EOF context supplies framing; four received bytes alone do not prove completion.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
A pipeline receives A then B, but response B is ready first. What is the selected HTTP/1.1 delivery order?
- A, B; ready B waits behind the first response.
- B, A; the first completed handler always writes first to the wire.
Read the explained answer
A, B; ready B waits behind the first response. — Pipelined responses match request order. PreparedOrder B, A does not make delivery B, A.
When is this historical HTTP/1.0 response considered complete?
Selected lesson artifact fields; teaching example
- http10.contentLengthField
- null
- http10.completeBeforeClose
- false
- http10.completeAfterSuppliedClose
- true
- As soon as Çay appears; the body length is guessed.
- After the supplied connection close.
Read the explained answer
After the supplied connection close. — The selected close-delimited content ends at EOF; that connection is no longer reusable.
How does HTTP/1.1 separate two Content-Length responses in one byte stream? Why is a read-call boundary insufficient?
Read the explained answer
The parser finds the CRLF header boundary, consumes ten content octets for the first response, then the second start-line/headers and four octets. TCP reads need not align with message boundaries. Searching for another response by adding arbitrary whitespace after the body is not this fixture’s length framing.
□ I used content octets for framing.
□ I did not treat TCP-read boundaries as HTTP boundaries.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- RFC 1945 — HTTP/1.0 (historical informational)1.3 Overall Operation · 7.2.2 Length
- RFC 9112 — HTTP/1.12.1 Message Format · 6.3 Message Body Length · 8 Handling Incomplete Messages · 9.3 Persistence · 9.3.2 Pipelining · 9.4 Concurrency