Skip to content

feat: add HTTP/1.1 request serializer - #12

Merged
zuudevs merged 6 commits into
mainfrom
feat/http-request-serializer
Sep 14, 2026
Merged

zuudevs merged 6 commits into
mainfrom
feat/http-request-serializer

Conversation

@zuudevs

@zuudevs zuudevs commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the internal HTTP/1.1 request serializer on top of the merged Request, Headers, and Url data model.

Added

  • src/http/request_serializer.hpp
    • SerializedRequest with parsed Url, owned header block, and borrowed body view
    • avoids copying request body bytes just to build wire data
  • src/http/request_serializer.cpp
    • serializes all v1 methods: GET, HEAD, POST, PUT, PATCH, DELETE
    • emits origin-form request target and HTTP/1.1
    • automatically generates Host when absent
    • formats bracketed IPv6 literals correctly in generated Host
    • preserves explicit URL ports in Host
    • serializes caller headers in insertion order
    • automatically generates Content-Length for non-empty bodies when absent
    • validates caller-provided Content-Length against body size
    • rejects duplicate Host / Content-Length
    • rejects request Transfer-Encoding because v1 request chunking is out of scope
    • validates header names as HTTP token characters
    • rejects CR/LF/control-byte header injection
  • tests/request_serializer_test.cpp
    • exact GET wire framing
    • all supported methods
    • duplicate custom headers
    • caller-provided Host override
    • explicit port and IPv6 Host formatting
    • zero-copy body view
    • Content-Length generation/validation
    • invalid header/framing cases
    • URL error propagation

Serialization model

The serializer intentionally produces two output segments: an owned request head and the original borrowed request body. Future Client execution can therefore call write_all(head) followed by write_all(body) without allocating a second full request buffer.

Scope

This PR does not write bytes to a socket, parse responses, implement redirects, or add Client. The next step can build the incremental HTTP/1.1 response parser on top of TcpConnection::read_some().

@zuudevs
zuudevs merged commit 8d113de into main Sep 14, 2026
6 checks passed
@zuudevs
zuudevs deleted the feat/http-request-serializer branch September 14, 2026 22:45

@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: 34e6d4b422

ℹ️ 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".


if (ascii_iequals(field.name, "Host")) {
++host_count;
if (field.value.empty()) {

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 whitespace-only Host values

When the caller supplies a whitespace-only Host value such as "\t", valid_header_value accepts the tab and this raw emptiness check passes. Serialization then succeeds with a semantically empty Host header while suppressing generation from the URL, producing an invalid HTTP/1.1 request that servers can reject. Check for an empty value after removing optional whitespace, or fully validate the Host authority.

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