Skip to content

Commit

Permalink
http: split set-cookie when using setHeaders
Browse files Browse the repository at this point in the history
PR-URL: nodejs#51649
Fixes: nodejs#51599
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Akhil Marsonya <akhil.marsonya27@gmail.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
  • Loading branch information
marco-ippolito authored and rdw-msft committed Feb 9, 2024
1 parent cac3288 commit 3d0a352
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
23 changes: 21 additions & 2 deletions lib/_http_outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -728,8 +728,27 @@ OutgoingMessage.prototype.setHeaders = function setHeaders(headers) {
throw new ERR_INVALID_ARG_TYPE('headers', ['Headers', 'Map'], headers);
}

for (const key of headers.keys()) {
this.setHeader(key, headers.get(key));
// Headers object joins multiple cookies with a comma when using
// the getter to retrieve the value,
// unless iterating over the headers directly.
// We also cannot safely split by comma.
// To avoid setHeader overwriting the previous value we push
// set-cookie values in array and set them all at once.
const cookies = [];

for (const { 0: key, 1: value } of headers) {
if (key === 'set-cookie') {
if (ArrayIsArray(value)) {
cookies.push(...value);
} else {
cookies.push(value);
}
continue;
}
this.setHeader(key, value);
}
if (cookies.length) {
this.setHeader('set-cookie', cookies);
}

return this;
Expand Down
43 changes: 43 additions & 0 deletions test/parallel/test-http-response-setheaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,46 @@ const assert = require('assert');
});
}));
}

{
const server = http.createServer({ requireHostHeader: false }, common.mustCall((req, res) => {
const headers = new Headers();
headers.append('Set-Cookie', 'a=b');
headers.append('Set-Cookie', 'c=d');
res.setHeaders(headers);
res.end();
}));

server.listen(0, common.mustCall(() => {
http.get({ port: server.address().port }, (res) => {
assert(Array.isArray(res.headers['set-cookie']));
assert.strictEqual(res.headers['set-cookie'].length, 2);
assert.strictEqual(res.headers['set-cookie'][0], 'a=b');
assert.strictEqual(res.headers['set-cookie'][1], 'c=d');
res.resume().on('end', common.mustCall(() => {
server.close();
}));
});
}));
}

{
const server = http.createServer({ requireHostHeader: false }, common.mustCall((req, res) => {
const headers = new Map();
headers.set('Set-Cookie', ['a=b', 'c=d']);
res.setHeaders(headers);
res.end();
}));

server.listen(0, common.mustCall(() => {
http.get({ port: server.address().port }, (res) => {
assert(Array.isArray(res.headers['set-cookie']));
assert.strictEqual(res.headers['set-cookie'].length, 2);
assert.strictEqual(res.headers['set-cookie'][0], 'a=b');
assert.strictEqual(res.headers['set-cookie'][1], 'c=d');
res.resume().on('end', common.mustCall(() => {
server.close();
}));
});
}));
}

0 comments on commit 3d0a352

Please sign in to comment.