From a3f494bf5b88d6856297a852ce9b2d476fd3594b Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Thu, 29 Feb 2024 03:59:19 -0500 Subject: [PATCH] Properly parse set-cookie header using http2 (#2886) * Properly parse set-cookie header using http2 * :lipstick: Co-authored-by: tsctx <91457664+tsctx@users.noreply.github.com> --------- Co-authored-by: tsctx <91457664+tsctx@users.noreply.github.com> --- lib/web/fetch/index.js | 10 +++++++++- test/fetch/cookies.js | 45 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index 0ae6a704e11..37e269fbc93 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -2145,7 +2145,15 @@ 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 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(key, value, 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']) +})