mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-03 07:54:40 +08:00
Send repeated Set-Cookie request headers as one combined line
Headers stores each Set-Cookie value separately, but undici dispatches its header list's combined value: one line with the values joined by ", " at the position of the first one. fetch() wrote one line per value. The request serializer now joins later Set-Cookie values into the first entry and skips the rest, for every HeadersInit form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
77b137268d
commit
46d238fc0a
@@ -4454,14 +4454,39 @@ static bool sf_start_hop(SfTransfer *t) {
|
||||
}
|
||||
if (connection_close) sf_push_header_text(headers, "connection", "close", 5);
|
||||
else sf_push_header_text(headers, "connection", "keep-alive", 10);
|
||||
/* Headers keeps each Set-Cookie value separately, but undici sends its
|
||||
* header list's combined value: one line, the values joined by ", ",
|
||||
* at the position of the first one. */
|
||||
bool set_cookie_sent = false;
|
||||
for (size_t i = 0; i + 1 < user_len; i += 2) {
|
||||
ScrStr *name = scr_arr_get_ref(t->headers, (double)i);
|
||||
ScrStr *value = scr_arr_get_ref(t->headers, (double)(i + 1));
|
||||
if (sf_eq_ci(name, "host") || sf_eq_ci(name, "connection")) {
|
||||
if (sf_eq_ci(name, "host") || sf_eq_ci(name, "connection") ||
|
||||
(set_cookie_sent && sf_eq_ci(name, "set-cookie"))) {
|
||||
scr_str_release(name);
|
||||
scr_str_release(value);
|
||||
continue;
|
||||
}
|
||||
if (sf_eq_ci(name, "set-cookie")) {
|
||||
set_cookie_sent = true;
|
||||
for (size_t j = i + 2; j + 1 < user_len; j += 2) {
|
||||
ScrStr *later = scr_arr_get_ref(t->headers, (double)j);
|
||||
bool match = sf_eq_ci(later, "set-cookie");
|
||||
scr_str_release(later);
|
||||
if (!match) continue;
|
||||
ScrStr *next = scr_arr_get_ref(t->headers, (double)(j + 1));
|
||||
size_t joined_len = value->len + 2 + next->len;
|
||||
char *joined = malloc(joined_len ? joined_len : 1);
|
||||
if (!joined) sf_oom();
|
||||
memcpy(joined, value->data, value->len);
|
||||
memcpy(joined + value->len, ", ", 2);
|
||||
memcpy(joined + value->len + 2, next->data, next->len);
|
||||
scr_str_release(next);
|
||||
scr_str_release(value);
|
||||
value = scr_str_new(joined, joined_len);
|
||||
free(joined);
|
||||
}
|
||||
}
|
||||
scr_arr_push_ref(headers, name);
|
||||
scr_arr_push_ref(headers, value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// fetch() sends its header list's combined values: repeated Set-Cookie
|
||||
// request headers go out as one line, the values joined by ", ", at the
|
||||
// position of the first one, whatever form the headers were given in.
|
||||
import { createServer } from "node:http";
|
||||
|
||||
function shown(raw: string[]): string {
|
||||
const lines: string[] = [];
|
||||
for (let i = 0; i < raw.length; i += 2) {
|
||||
const name = raw[i]!;
|
||||
const lower = name.toLowerCase();
|
||||
if (lower === "host" || lower === "connection" || lower.startsWith("accept") || lower.startsWith("sec-") || lower === "user-agent") continue;
|
||||
lines.push(`${name}: ${raw[i + 1]}`);
|
||||
}
|
||||
return lines.join(" | ");
|
||||
}
|
||||
|
||||
const server = createServer((req, res) => {
|
||||
res.end(shown(req.rawHeaders));
|
||||
});
|
||||
|
||||
server.listen(0, "127.0.0.1", async () => {
|
||||
const addr = server.address();
|
||||
const port = typeof addr === "object" && addr ? addr.port : 0;
|
||||
const url = `http://127.0.0.1:${port}/`;
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("set-cookie", "a=1");
|
||||
headers.append("x-first", "1");
|
||||
headers.append("set-cookie", "b=2");
|
||||
console.log(await (await fetch(url, { headers })).text());
|
||||
|
||||
const pairs: [string, string][] = [
|
||||
["x-before", "0"],
|
||||
["set-cookie", "c=3"],
|
||||
["set-cookie", "d=4; Path=/"],
|
||||
];
|
||||
console.log(await (await fetch(url, { headers: pairs })).text());
|
||||
|
||||
console.log(await (await fetch(url, { headers: { "set-cookie": "e=5", "x-record": "r" } })).text());
|
||||
|
||||
const single = new Headers({ "set-cookie": "only=1" });
|
||||
console.log(await (await fetch(url, { headers: single })).text());
|
||||
server.close();
|
||||
});
|
||||
Reference in New Issue
Block a user