diff --git a/lib/handler/wrap-handler.js b/lib/handler/wrap-handler.js index 9a0dee3d069..47caa5fa68b 100644 --- a/lib/handler/wrap-handler.js +++ b/lib/handler/wrap-handler.js @@ -53,8 +53,7 @@ module.exports = class WrapHandler { onRequestUpgrade (controller, statusCode, headers, socket) { const rawHeaders = [] for (const [key, val] of Object.entries(headers)) { - // TODO (fix): What if val is Array - rawHeaders.push(Buffer.from(key), Buffer.from(val)) + rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) } this.#handler.onUpgrade?.(statusCode, rawHeaders, socket) @@ -63,8 +62,7 @@ module.exports = class WrapHandler { onResponseStart (controller, statusCode, headers, statusMessage) { const rawHeaders = [] for (const [key, val] of Object.entries(headers)) { - // TODO (fix): What if val is Array - rawHeaders.push(Buffer.from(key), Buffer.from(val)) + rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) } if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) { @@ -81,8 +79,7 @@ module.exports = class WrapHandler { onResponseEnd (controller, trailers) { const rawTrailers = [] for (const [key, val] of Object.entries(trailers)) { - // TODO (fix): What if val is Array - rawTrailers.push(Buffer.from(key), Buffer.from(val)) + rawTrailers.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) } this.#handler.onComplete?.(rawTrailers) diff --git a/test/client-node-max-header-size.js b/test/client-node-max-header-size.js index 4c23113dde8..2d1d8cbbcf2 100644 --- a/test/client-node-max-header-size.js +++ b/test/client-node-max-header-size.js @@ -25,7 +25,7 @@ describe("Node.js' --max-http-header-size cli option", () => { test("respect Node.js' --max-http-header-size", async (t) => { t = tspl(t, { plan: 6 }) - const command = 'node -e "require(\'.\').request(\'http://localhost:' + server.address().port + '\')"' + const command = 'node --disable-warning=ExperimentalWarning -e "require(\'.\').request(\'http://localhost:' + server.address().port + '\')"' exec(`${command} --max-http-header-size=1`, { stdio: 'pipe' }, (err, stdout, stderr) => { t.strictEqual(err.code, 1) @@ -44,7 +44,7 @@ describe("Node.js' --max-http-header-size cli option", () => { test('--max-http-header-size with Client API', async (t) => { t = tspl(t, { plan: 6 }) - const command = 'node -e "new (require(\'.\').Client)(new URL(\'http://localhost:200\'))"' + const command = 'node --disable-warning=ExperimentalWarning -e "new (require(\'.\').Client)(new URL(\'http://localhost:200\'))"' exec(`${command} --max-http-header-size=0`, { stdio: 'pipe' }, (err, stdout, stderr) => { t.strictEqual(err.code, 1) diff --git a/test/issue-3934.js b/test/issue-3934.js new file mode 100644 index 00000000000..19c1544c213 --- /dev/null +++ b/test/issue-3934.js @@ -0,0 +1,32 @@ +'use strict' + +const { test } = require('node:test') +const { createServer } = require('node:http') +const { once } = require('node:events') +const assert = require('node:assert') +const { Agent, RetryAgent, request } = require('..') + +// https://github.com/nodejs/undici/issues/3934 +test('WrapHandler works with multiple header values', async (t) => { + const server = createServer(async (_req, res) => { + const headers = [ + ['set-cookie', 'a'], + ['set-cookie', 'b'], + ['set-cookie', 'c'] + ] + res.writeHead(200, headers) + res.end() + }).listen(0) + + await once(server, 'listening') + t.after(() => server.close()) + + const agent = new Agent() + const retryAgent = new RetryAgent(agent) + + const { + headers + } = await request(`http://localhost:${server.address().port}`, { dispatcher: retryAgent }) + + assert.deepStrictEqual(headers['set-cookie'], ['a', 'b', 'c']) +})