diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 5350c08d4ce75d..b512c7f60f9dee 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -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 owerwriting 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; diff --git a/test/parallel/test-http-response-setheaders.js b/test/parallel/test-http-response-setheaders.js index c1f697fa5d6cfe..2f52c54a49760f 100644 --- a/test/parallel/test-http-response-setheaders.js +++ b/test/parallel/test-http-response-setheaders.js @@ -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(); + })); + }); + })); +}