From 5ff9a0fdad3d95c20dcc521f8e7b728930c22146 Mon Sep 17 00:00:00 2001
From: Matthew Aitken <maitken033380023@gmail.com>
Date: Tue, 10 Dec 2024 14:56:57 -0500
Subject: [PATCH 1/2] support array of headers in WrapHandler

---
 lib/handler/wrap-handler.js |  9 +++------
 test/issue-3934.js          | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 6 deletions(-)
 create mode 100644 test/issue-3934.js

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/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'])
+})

From b278371670432d3cbdd76600b46042c5d24cea47 Mon Sep 17 00:00:00 2001
From: Matthew Aitken <maitken033380023@gmail.com>
Date: Tue, 10 Dec 2024 15:02:26 -0500
Subject: [PATCH 2/2] fixup

---
 test/client-node-max-header-size.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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)
