Skip to content

fix: add Headers.getSetCookie() and fix Set-Cookie iterator folding#149

Open
DepsCian wants to merge 1 commit into
sqdshguy:masterfrom
DepsCian:fix/set-cookie-headers-compliance
Open

fix: add Headers.getSetCookie() and fix Set-Cookie iterator folding#149
DepsCian wants to merge 1 commit into
sqdshguy:masterfrom
DepsCian:fix/set-cookie-headers-compliance

Conversation

@DepsCian

@DepsCian DepsCian commented Jun 3, 2026

Copy link
Copy Markdown

Fixes #148

Problem

Headers.get("set-cookie") comma-folds multiple Set-Cookie values into a single string ("a=1, b=2"), violating RFC 6265 §3 and the Fetch spec which explicitly forbids combining Set-Cookie fields. The getSetCookie() method required by the spec does not exist.

This causes silent cookie loss when multiple Set-Cookie headers are present (e.g. __Secure-next-auth.session-token + __cf_bm) — a common pattern in NextAuth.js flows.

Changes

src/wreq-js.ts — Headers class:

  1. Added getSetCookie(): string[] — returns individual Set-Cookie values as an array, matching the native Fetch API. Returns [] when absent.

  2. Fixed [Symbol.iterator] — yields one [name, value] tuple per Set-Cookie value instead of comma-folding. All other headers retain the existing values.join(", ") behavior.

  3. Fixed toObject() — iterates store.values() directly (bypasses the multi-tuple iterator expansion) to avoid duplicate keys in the returned Record<string, string>. Comma-joins all headers including Set-Cookie, consistent with get().

src/test/unit/headers.spec.ts — new test file:

12 test cases covering:

  • getSetCookie() — empty, single, multiple, comma-in-Expires field
  • get("set-cookie") — backward-compatible comma-joined string
  • Iterator — one tuple per Set-Cookie value
  • toTuples() — separate tuples per Set-Cookie value
  • toObject() — comma-join (lossy but consistent with Record<string, string>)
  • Round-trip via new Headers(existingHeaders) — preserves individual Set-Cookie values
  • keys() / forEach() — one entry per Set-Cookie value
  • Non-Set-Cookie multi-value — still comma-joins (existing behavior unchanged)

src/test/run-with-local-server.ts — auto-discovers unit/*.spec.ts alongside existing http/*.spec.ts.

Backward Compatibility

Method Before After
get("set-cookie") "a=1, b=2" "a=1, b=2" (unchanged)
getSetCookie() N/A (missing) ["a=1", "b=2"]
toTuples() for Set-Cookie ["set-cookie", "a=1, b=2"] ["set-cookie", "a=1"], ["set-cookie", "b=2"]
toObject() for Set-Cookie "a=1, b=2" "a=1, b=2" (unchanged)
get("X-Test") multi-value "alpha, beta" "alpha, beta" (unchanged)

get() remains comma-joined for all headers including set-cookie, matching the WHATWG spec's acknowledged legacy behavior. getSetCookie() is the authoritative accessor.

Verification

✔ Headers — Set-Cookie spec compliance (12 tests, 0 failures)
✔ supports the Headers helper API (existing test, backward compat confirmed)
✔ TypeScript typecheck: clean
✔ Biome lint: clean

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.

fix: Headers.get("set-cookie") folds multiple Set-Cookie values into invalid comma-joined string; getSetCookie() missing

1 participant