Skip to content

feat: add HTTP/1.1 chunked transfer decoder - #14

Merged
zuudevs merged 8 commits into
mainfrom
feat/http-chunked-decoder
Sep 14, 2026
Merged

zuudevs merged 8 commits into
mainfrom
feat/http-chunked-decoder

Conversation

@zuudevs

@zuudevs zuudevs commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Summary

Completes HTTP/1.1 response body framing for Transfer-Encoding: chunked and integrates it directly into the incremental response parser.

Added

  • src/http/chunked_decoder.hpp / .cpp
    • incremental chunk-size parsing in hexadecimal
    • arbitrary TCP/feed boundaries
    • chunk payload accumulation without exposing framing bytes
    • mandatory CRLF validation after each chunk payload
    • chunk-extension consumption
    • terminal zero-size chunk handling
    • trailer-section validation and consumption
    • rejects malformed chunk sizes/framing and forbidden framing fields in trailers
    • preserves bytes following the terminal trailer block for connection reuse / the next response
  • ResponseParser integration
    • valid Transfer-Encoding: chunked is decoded internally instead of returning a handoff state
    • parser now returns only NeedMore or Complete
    • decoded chunk bytes populate the normal owning Response body
    • premature EOF during chunked framing maps to UnexpectedEof
    • chunked responses remain reusable when normal HTTP connection semantics permit it
  • tests
    • multiple chunks
    • one-byte-at-a-time decoding
    • chunk extensions
    • trailer consumption
    • following-response byte preservation
    • invalid hexadecimal size
    • invalid chunk-data CRLF
    • malformed/forbidden trailer fields
    • incomplete chunks
    • full ResponseParser chunked integration
    • premature EOF

Trailer policy

Trailer fields are syntax-validated and consumed so message completion is unambiguous, but they are not merged into Response::headers() in v1. Framing-critical trailer fields such as Content-Length and Transfer-Encoding are rejected.

Scope

This PR completes the v1 response framing primitives for Content-Length, close-delimited, no-body, and chunked responses. It still does not add socket orchestration, redirects, or the public Client execution path.

@zuudevs
zuudevs merged commit 1976d62 into main Sep 14, 2026
6 checks passed
@zuudevs
zuudevs deleted the feat/http-chunked-decoder branch September 14, 2026 23:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 364345a15f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +103 to +104
const std::size_t semicolon = line.find(';');
const std::string_view size_text = line.substr(0, semicolon);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip BWS before parsing an extended chunk size

When a server sends a chunk line such as 4 ;foo=bar\r\n, the HTTP chunk-extension grammar permits the whitespace before ; as BWS and requires recipients to tolerate it, but size_text remains "4 ", so from_chars rejects an otherwise parseable response as InvalidChunkSize. Remove the permitted trailing BWS from the size portion before parsing it.

Useful? React with 👍 / 👎.

Comment on lines +91 to +95
for (const unsigned char ch : extension) {
if (ch == '\t') {
continue;
}
if (ch < 0x20 || ch == 0x7f) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject syntactically invalid chunk extensions

When a malformed peer sends an extension such as 4;\r\n or 4;foo="unterminated\r\n, this validator accepts it because it only rejects control bytes, and the response completes successfully. Chunk extensions require a nonempty token name and, when present, a token or valid quoted-string value, so the decoder needs to validate that grammar to satisfy its malformed-framing error contract.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant