Skip to content

Commit 3c20536

Browse files
fix(fetch): fix headers.entries/values/forEach iteration for Set-Cookie headers (#89)
* Fix headers.entries/values/forEach handling of setCookie * Fix headers.entries/values/forEach handling of setCookie * Add changeset * chore: fix changeset --------- Co-authored-by: Matt Brophy <[email protected]>
1 parent ace4223 commit 3c20536

File tree

3 files changed

+86
-3
lines changed

3 files changed

+86
-3
lines changed

.changeset/good-badgers-sleep.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@web-std/fetch": patch
3+
---
4+
5+
Fix `headers.entries`/`values`/`forEach` iteration for `Set-Cookie` headers

packages/fetch/src/headers.js

+24-3
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,14 @@ export default class Headers extends URLSearchParams {
190190
*/
191191
forEach(callback, thisArg = undefined) {
192192
for (const name of this.keys()) {
193-
Reflect.apply(callback, thisArg, [this.get(name), name, this]);
193+
if (name.toLowerCase() === 'set-cookie') {
194+
let cookies = this.getAll(name);
195+
while (cookies.length > 0) {
196+
Reflect.apply(callback, thisArg, [cookies.shift(), name, this])
197+
}
198+
} else {
199+
Reflect.apply(callback, thisArg, [this.get(name), name, this]);
200+
}
194201
}
195202
}
196203

@@ -199,7 +206,14 @@ export default class Headers extends URLSearchParams {
199206
*/
200207
* values() {
201208
for (const name of this.keys()) {
202-
yield /** @type {string} */(this.get(name));
209+
if (name.toLowerCase() === 'set-cookie') {
210+
let cookies = this.getAll(name);
211+
while (cookies.length > 0) {
212+
yield /** @type {string} */(cookies.shift());
213+
}
214+
} else {
215+
yield /** @type {string} */(this.get(name));
216+
}
203217
}
204218
}
205219

@@ -208,7 +222,14 @@ export default class Headers extends URLSearchParams {
208222
*/
209223
* entries() {
210224
for (const name of this.keys()) {
211-
yield [name, /** @type {string} */(this.get(name))];
225+
if (name.toLowerCase() === 'set-cookie') {
226+
let cookies = this.getAll(name);
227+
while (cookies.length > 0) {
228+
yield [name, /** @type {string} */(cookies.shift())];
229+
}
230+
} else {
231+
yield [name, /** @type {string} */(this.get(name))];
232+
}
212233
}
213234
}
214235

packages/fetch/test/headers.js

+57
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,26 @@ describe('Headers', () => {
6969
expect({key: 'content-type', value: 'text/html', object: headers}).to.deep.equal(results[1]);
7070
});
7171

72+
it('should allow iterating through multiple set-cookie headers with forEach', () => {
73+
let headers = new Headers([
74+
['a', '1'],
75+
['Set-Cookie', 'b=2']
76+
]);
77+
headers.append('Set-Cookie', 'c=3');
78+
expect(headers.entries()).to.be.iterable;
79+
80+
const results = [];
81+
headers.forEach((value, key, object) => {
82+
results.push({value, key, object});
83+
});
84+
85+
expect(results).to.deep.equal([
86+
{ value: '1', key: 'a', object: headers },
87+
{ value: 'b=2', key: 'set-cookie', object: headers },
88+
{ value: 'c=3', key: 'set-cookie', object: headers },
89+
]);
90+
})
91+
7292
it('should set "this" to undefined by default on forEach', () => {
7393
const headers = new Headers({Accept: 'application/json'});
7494
headers.forEach(function () {
@@ -103,8 +123,25 @@ describe('Headers', () => {
103123
['b', '2, 3'],
104124
['c', '4']
105125
]);
126+
106127
});
107128

129+
it('should allow iterating through multiple set-cookie headers with for-of loop', () => {
130+
let headers = new Headers([
131+
['a', '1'],
132+
['Set-Cookie', 'b=2']
133+
]);
134+
headers.append('Set-Cookie', 'c=3');
135+
expect(headers.entries()).to.be.iterable;
136+
137+
const result = [];
138+
for (const pair of headers) {
139+
result.push(pair);
140+
}
141+
142+
expect(result).to.deep.equal([['a', '1'], ['set-cookie', 'b=2'], ['set-cookie', 'c=3']]);
143+
})
144+
108145
it('should allow iterating through all headers with entries()', () => {
109146
const headers = new Headers([
110147
['b', '2'],
@@ -121,6 +158,16 @@ describe('Headers', () => {
121158
]);
122159
});
123160

161+
it('should allow iterating through multiple set-cookie headers with entries()', ()=> {
162+
let headers = new Headers([
163+
['a', '1'],
164+
['Set-Cookie', 'b=2']
165+
]);
166+
headers.append('Set-Cookie', 'c=3');
167+
expect(headers.entries()).to.be.iterable
168+
.and.to.deep.iterate.over([['a', '1'], ['set-cookie', 'b=2'], ['set-cookie', 'c=3']]);
169+
})
170+
124171
it('should allow iterating through all headers with keys()', () => {
125172
const headers = new Headers([
126173
['b', '2'],
@@ -145,6 +192,16 @@ describe('Headers', () => {
145192
.and.to.iterate.over(['1', '2, 3', '4']);
146193
});
147194

195+
it('should allow iterating through multiple set-cookie headers with values()', ()=> {
196+
let headers = new Headers([
197+
['a', '1'],
198+
['Set-Cookie', 'b=2']
199+
]);
200+
headers.append('Set-Cookie', 'c=3');
201+
expect(headers.values()).to.be.iterable
202+
.and.to.iterate.over(['1', 'b=2', 'c=3']);
203+
})
204+
148205
it('should reject illegal header', () => {
149206
const headers = new Headers();
150207
expect(() => new Headers({'He y': 'ok'})).to.throw(TypeError);

0 commit comments

Comments
 (0)