Skip to content

Commit 2971289

Browse files
authored
fix(http): correct Response header initialization to support cloning (fix #14892) (#3252)
Previously, headers were patched onto the Response object after construction, which bypassed the internal header list and caused `response.clone().headers` to be empty. This change passes the headers directly to the Response constructor, ensuring they are properly stored and clonable.
1 parent 6c3da6d commit 2971289

3 files changed

Lines changed: 30 additions & 8 deletions

File tree

.changes/change-pr-3252.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"http": patch
3+
"http-js": patch
4+
---
5+
6+
Correct Response header initialization to support cloning and ensure Set-Cookie visibility.

plugins/http/api-iife.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/http/guest-js/index.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,14 +287,30 @@ export async function fetch(
287287
statusText
288288
})
289289

290-
// Set `Response` properties that are ignored by the
291-
// constructor, like url and some headers
292-
//
293-
// Since url and headers are read only properties
294-
// this is the only way to set them.
295-
Object.defineProperty(res, 'url', { value: url })
290+
// `Response.url` cannot be set via the constructor, so we define it manually
291+
Object.defineProperty(res, 'url', { value: url, writable: false })
292+
293+
// Expose `set-cookie` via `response.headers` (and `getSetCookie()` where
294+
// supported). This is not Fetch-spec compliant for network responses in
295+
// browsers, where `set-cookie` is treated as a forbidden response
296+
// header and is generally not readable from JavaScript.
296297
Object.defineProperty(res, 'headers', {
297-
value: new Headers(responseHeaders)
298+
value: new Headers(responseHeaders),
299+
writable: false
300+
})
301+
302+
// Patch clone() per-instance so cloning preserves the overridden properties
303+
const originalClone = res.clone.bind(res)
304+
Object.defineProperty(res, 'clone', {
305+
value: () => {
306+
const cloned = originalClone()
307+
Object.defineProperty(cloned, 'url', { value: url, writable: false })
308+
Object.defineProperty(cloned, 'headers', {
309+
value: new Headers(responseHeaders),
310+
writable: false
311+
})
312+
return cloned
313+
}
298314
})
299315

300316
return res

0 commit comments

Comments
 (0)