Skip to content

refactor: rework how httpclient headers work - #3118

Merged
karlseguin merged 1 commit into
mainfrom
refactor-http-client-headers
Aug 3, 2026
Merged

refactor: rework how httpclient headers work#3118
karlseguin merged 1 commit into
mainfrom
refactor-http-client-headers

Conversation

@karlseguin

Copy link
Copy Markdown
Collaborator

Adding headers to an HTTP request was a bit awkward due to my desire to avoid having an intermediate representation (e.g. an ArrayList(Header)). Going straight to a curl slist avoids double-copying the headers (first to Zig, then to curl).

But the CORS work (#3002) showcases that this micro-optimization simply isn't worth it, since it needs that intermediate representation anyways.

And, this change isn't just for CORS. Headers have been a silly pain in the past like unclear ownership, and messy APIs used in a lot of places (WebBotAuth, WebSocket, Fetch, ...)

This new approach stores headers on the transfer in an ArrayList. The API is:

const transfer = try client.newRequest(.{...}, owner);
{
    errdefer transfer.deinit();
    try transfer.addHeader("Over", "9000", .{});
}
try transfer.submit();

This:
1 - Eliminates ambiguity about errdefer cleanup responsibility
2 - Eliminates a bunch of stringZ concat that Frame, Config, CDP were doing
3 - Transfer.arena is now available for headers

Adding headers to an HTTP request was a bit awkward due to my desire to avoid
having an intermediate representation (e.g. an ArrayList(Header)). Going
straight to a curl slist avoids double-copying the headers (first to Zig, then
to curl).

But the CORS work (#3002) showcases
that this micro-optimization simply isn't worth it, since it needs that
intermediate representation anyways.

And, this change isn't just for CORS. Headers have been a silly pain in the past
like unclear ownership, and messy APIs used in _a lot_ of places (WebBotAuth,
WebSocket, Fetch, ...)

This new approach stores headers on the transfer in an ArrayList. The API is:

```
const transfer = try client.newRequest(.{...}, owner);
{
    errdefer transfer.deinit();
    try transfer.addHeader("Over", "9000", .{});
}
try transfer.submit();
```

This:
1 - Eliminates ambiguity about errdefer cleanup responsibility
2 - Eliminates a bunch of stringZ concat that Frame, Config, CDP were doing
3 - Transfer.arena is now available for headers
@karlseguin
karlseguin merged commit 5f88b33 into main Aug 3, 2026
26 checks passed
@karlseguin
karlseguin deleted the refactor-http-client-headers branch August 3, 2026 22:42
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant