From 5d7e51d04e013c0ccedb9c0731d16b2d93544bb8 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Thu, 29 Feb 2024 07:09:34 +0000 Subject: [PATCH 1/2] Properly parse set-cookie header using http2 --- lib/web/fetch/index.js | 9 ++++++++- test/fetch/cookies.js | 45 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index 0ae6a704e11..dcabc32cfd6 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -2145,7 +2145,14 @@ async function httpNetworkFetch ( const keys = Object.keys(rawHeaders) for (let i = 0; i < keys.length; ++i) { // The header names are already in lowercase. - headersList.append(keys[i], rawHeaders[keys[i]], true) + const values = rawHeaders[keys[i]] + if (Array.isArray(values)) { + for (const value of values) { + headersList.append(keys[i], value, true) + } + } else { + headersList.append(keys[i], values, true) + } } // For H2, The header names are already in lowercase, // so we can avoid the `HeadersList#get` call here. diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index c34f3dc921a..3bc69c6837b 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -5,8 +5,11 @@ const { createServer } = require('node:http') const { test } = require('node:test') const assert = require('node:assert') const { tspl } = require('@matteo.collina/tspl') -const { fetch, Headers } = require('../..') +const { Client, fetch, Headers } = require('../..') const { closeServerAsPromise } = require('../utils/node-http') +const pem = require('https-pem') +const { createSecureServer } = require('node:http2') +const { closeClientAndServerAsPromise } = require('../utils/node-http') test('Can receive set-cookie headers from a server using fetch - issue #1262', async (t) => { const server = createServer((req, res) => { @@ -66,3 +69,43 @@ test('Cookie header is delimited with a semicolon rather than a comma - issue #1 ] }) }) + +test('Can receive set-cookie headers from a http2 server using fetch - issue #2885', async (t) => { + const server = createSecureServer(pem) + server.on('stream', async (stream, headers) => { + stream.respond({ + 'content-type': 'text/plain; charset=utf-8', + 'x-method': headers[':method'], + 'set-cookie': 'Space=Cat; Secure; HttpOnly', + ':status': 200 + }) + + stream.end('test') + }) + + server.listen() + await once(server, 'listening') + + const client = new Client(`https://localhost:${server.address().port}`, { + connect: { + rejectUnauthorized: false + }, + allowH2: true + }) + + const response = await fetch( + `https://localhost:${server.address().port}/`, + // Needs to be passed to disable the reject unauthorized + { + method: 'GET', + dispatcher: client, + headers: { + 'content-type': 'text-plain' + } + } + ) + + t.after(closeClientAndServerAsPromise(client, server)) + + assert.deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) +}) From af4134f35ba0a042837df504dbd165ffec404f99 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Thu, 29 Feb 2024 02:36:43 -0500 Subject: [PATCH 2/2] :lipstick: Co-authored-by: tsctx <91457664+tsctx@users.noreply.github.com> --- lib/web/fetch/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index dcabc32cfd6..37e269fbc93 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -2145,13 +2145,14 @@ async function httpNetworkFetch ( const keys = Object.keys(rawHeaders) for (let i = 0; i < keys.length; ++i) { // The header names are already in lowercase. - const values = rawHeaders[keys[i]] - if (Array.isArray(values)) { - for (const value of values) { - headersList.append(keys[i], value, true) + const key = keys[i] + const value = rawHeaders[key] + if (key === 'set-cookie') { + for (let j = 0; j < value.length; ++j) { + headersList.append(key, value[j], true) } } else { - headersList.append(keys[i], values, true) + headersList.append(key, value, true) } } // For H2, The header names are already in lowercase,