From a003112a932de8049e6c06c86df190d5b2bd372a Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 8 Sep 2025 00:28:26 +0200 Subject: [PATCH 1/8] test: warmup for macos and node 20 --- test/fetch/encoding.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/fetch/encoding.js b/test/fetch/encoding.js index 077b4a401ce..0da14691a86 100644 --- a/test/fetch/encoding.js +++ b/test/fetch/encoding.js @@ -54,6 +54,15 @@ describe('content-encoding handling', () => { server.close() }) + test('warmup', async (t) => { + try { + await fetch(`http://localhost:${server.address().port}`, { + keepalive: false, + headers: { 'accept-encoding': 'deflate, gzip' } + }) + } catch { } + }) + test('content-encoding header', async (t) => { const { strictEqual } = tspl(t, { plan: 3 }) From 04081e9385338431f0aa1b0eef947e94d7aabf7d Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Wed, 10 Sep 2025 09:33:11 +0200 Subject: [PATCH 2/8] refactor cookies.js --- test/fetch/cookies.js | 160 ++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 76 deletions(-) diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index 8a141004c6e..8e4a683c262 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -2,110 +2,118 @@ const { once } = require('node:events') const { createServer } = require('node:http') -const { test } = require('node:test') +const { test, describe, before, after } = require('node:test') const assert = require('node:assert') +const { stringify: qsStringify } = require('node:querystring') const { tspl } = require('@matteo.collina/tspl') const { Client, fetch, Headers } = require('../..') -const { closeServerAsPromise } = require('../utils/node-http') const pem = require('@metcoder95/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({ joinDuplicateHeaders: true }, (req, res) => { - res.setHeader('set-cookie', 'name=value; Domain=example.com') - res.end() - }).listen(0) +describe('cookies', () => { + let server - t.after(closeServerAsPromise(server)) - await once(server, 'listening') - - const response = await fetch(`http://localhost:${server.address().port}`) - - assert.strictEqual(response.headers.get('set-cookie'), 'name=value; Domain=example.com') + before(() => { + server = createServer({ joinDuplicateHeaders: true }, (req, res) => { + const searchParams = new URL(req.url, 'http://localhost').searchParams + if (searchParams.has('set-cookie')) { + res.setHeader('set-cookie', searchParams.get('set-cookie')) + } + res.end(req.headers.cookie) + }) - const response2 = await fetch(`http://localhost:${server.address().port}`, { - credentials: 'include' + return once(server.listen(0), 'listening') }) - assert.strictEqual(response2.headers.get('set-cookie'), 'name=value; Domain=example.com') -}) - -test('Can send cookies to a server with fetch - issue #1463', async (t) => { - const server = createServer({ joinDuplicateHeaders: true }, (req, res) => { - assert.strictEqual(req.headers.cookie, 'value') - res.end() - }).listen(0) + after(() => { + server.close() + return once(server, 'close') + }) - t.after(closeServerAsPromise(server)) - await once(server, 'listening') + test('Can receive set-cookie headers from a server using fetch - issue #1262', async (t) => { + t = tspl(t, { plan: 2 }) - const headersInit = [ - new Headers([['cookie', 'value']]), - { cookie: 'value' }, - [['cookie', 'value']] - ] + const query = qsStringify({ + 'set-cookie': 'name=value; Domain=example.com' + }) + const response = await fetch(`http://localhost:${server.address().port}?${query}`) - for (const headers of headersInit) { - await fetch(`http://localhost:${server.address().port}`, { headers }) - } -}) + t.strictEqual(response.headers.get('set-cookie'), 'name=value; Domain=example.com') -test('Cookie header is delimited with a semicolon rather than a comma - issue #1905', async (t) => { - const { strictEqual } = tspl(t, { plan: 1 }) + const response2 = await fetch(`http://localhost:${server.address().port}?${query}`, { + credentials: 'include' + }) - const server = createServer({ joinDuplicateHeaders: true }, (req, res) => { - strictEqual(req.headers.cookie, 'FOO=lorem-ipsum-dolor-sit-amet; BAR=the-quick-brown-fox') - res.end() - }).listen(0) + t.strictEqual(response2.headers.get('set-cookie'), 'name=value; Domain=example.com') + }) - t.after(closeServerAsPromise(server)) - await once(server, 'listening') + test('Can send cookies to a server with fetch - issue #1463', async (t) => { + t = tspl(t, { plan: 3 }) - await fetch(`http://localhost:${server.address().port}`, { - headers: [ - ['cookie', 'FOO=lorem-ipsum-dolor-sit-amet'], - ['cookie', 'BAR=the-quick-brown-fox'] + const headersInit = [ + new Headers([['cookie', 'value']]), + { cookie: 'value' }, + [['cookie', 'value']] ] + + for (const headers of headersInit) { + const response = await fetch(`http://localhost:${server.address().port}`, { headers }) + const text = await response.text() + t.strictEqual(text, 'value') + } }) -}) -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 + test('Cookie header is delimited with a semicolon rather than a comma - issue #1905', async (t) => { + t = tspl(t, { plan: 1 }) + + const response = await fetch(`http://localhost:${server.address().port}`, { + headers: [ + ['cookie', 'FOO=lorem-ipsum-dolor-sit-amet'], + ['cookie', 'BAR=the-quick-brown-fox'] + ] }) - stream.end('test') + t.strictEqual(await response.text(), 'FOO=lorem-ipsum-dolor-sit-amet; BAR=the-quick-brown-fox') }) - server.listen() - await once(server, 'listening') + 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(0) + await once(server, 'listening') - const client = new Client(`https://localhost:${server.address().port}`, { - connect: { - rejectUnauthorized: false - }, - allowH2: true - }) + 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' + 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)) + t.after(closeClientAndServerAsPromise(client, server)) - assert.deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) + assert.deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) + }) }) From 15bcb46fb485f0b7792d730fbd301c9b1f91ff60 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 13 Sep 2025 00:45:41 +0200 Subject: [PATCH 3/8] maybe tspl is the culprit --- test/fetch/cookies.js | 34 ++++++++++++++-------------------- test/fetch/encoding.js | 32 ++++++++++---------------------- 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index 8e4a683c262..19785d3eab8 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -1,15 +1,13 @@ 'use strict' +const { strictEqual, deepStrictEqual } = require('node:assert').strict const { once } = require('node:events') const { createServer } = require('node:http') const { test, describe, before, after } = require('node:test') -const assert = require('node:assert') const { stringify: qsStringify } = require('node:querystring') -const { tspl } = require('@matteo.collina/tspl') const { Client, fetch, Headers } = require('../..') const pem = require('@metcoder95/https-pem') const { createSecureServer } = require('node:http2') -const { closeClientAndServerAsPromise } = require('../utils/node-http') describe('cookies', () => { let server @@ -31,26 +29,22 @@ describe('cookies', () => { return once(server, 'close') }) - test('Can receive set-cookie headers from a server using fetch - issue #1262', async (t) => { - t = tspl(t, { plan: 2 }) - + test('Can receive set-cookie headers from a server using fetch - issue #1262', async () => { const query = qsStringify({ 'set-cookie': 'name=value; Domain=example.com' }) const response = await fetch(`http://localhost:${server.address().port}?${query}`) - t.strictEqual(response.headers.get('set-cookie'), 'name=value; Domain=example.com') + strictEqual(response.headers.get('set-cookie'), 'name=value; Domain=example.com') const response2 = await fetch(`http://localhost:${server.address().port}?${query}`, { credentials: 'include' }) - t.strictEqual(response2.headers.get('set-cookie'), 'name=value; Domain=example.com') + strictEqual(response2.headers.get('set-cookie'), 'name=value; Domain=example.com') }) - test('Can send cookies to a server with fetch - issue #1463', async (t) => { - t = tspl(t, { plan: 3 }) - + test('Can send cookies to a server with fetch - issue #1463', async () => { const headersInit = [ new Headers([['cookie', 'value']]), { cookie: 'value' }, @@ -60,13 +54,11 @@ describe('cookies', () => { for (const headers of headersInit) { const response = await fetch(`http://localhost:${server.address().port}`, { headers }) const text = await response.text() - t.strictEqual(text, 'value') + strictEqual(text, 'value') } }) - test('Cookie header is delimited with a semicolon rather than a comma - issue #1905', async (t) => { - t = tspl(t, { plan: 1 }) - + test('Cookie header is delimited with a semicolon rather than a comma - issue #1905', async () => { const response = await fetch(`http://localhost:${server.address().port}`, { headers: [ ['cookie', 'FOO=lorem-ipsum-dolor-sit-amet'], @@ -74,12 +66,12 @@ describe('cookies', () => { ] }) - t.strictEqual(await response.text(), 'FOO=lorem-ipsum-dolor-sit-amet; BAR=the-quick-brown-fox') + strictEqual(await response.text(), 'FOO=lorem-ipsum-dolor-sit-amet; BAR=the-quick-brown-fox') }) - test('Can receive set-cookie headers from a http2 server using fetch - issue #2885', async (t) => { + test('Can receive set-cookie headers from a http2 server using fetch - issue #2885', async () => { const server = createSecureServer(pem) - server.on('stream', async (stream, headers) => { + server.on('stream', (stream, headers) => { stream.respond({ 'content-type': 'text/plain; charset=utf-8', 'x-method': headers[':method'], @@ -112,8 +104,10 @@ describe('cookies', () => { } ) - t.after(closeClientAndServerAsPromise(client, server)) + deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) - assert.deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) + await client.close() + server.close() + await once(server, 'close') }) }) diff --git a/test/fetch/encoding.js b/test/fetch/encoding.js index 0da14691a86..3132ab9ed26 100644 --- a/test/fetch/encoding.js +++ b/test/fetch/encoding.js @@ -1,9 +1,9 @@ 'use strict' +const { strictEqual } = require('node:assert').strict const { once } = require('node:events') const { createServer } = require('node:http') const { test, before, after, describe } = require('node:test') -const { tspl } = require('@matteo.collina/tspl') const { fetch } = require('../..') describe('content-encoding handling', () => { @@ -54,18 +54,16 @@ describe('content-encoding handling', () => { server.close() }) - test('warmup', async (t) => { - try { - await fetch(`http://localhost:${server.address().port}`, { - keepalive: false, - headers: { 'accept-encoding': 'deflate, gzip' } - }) - } catch { } - }) + // test('warmup', async (t) => { + // try { + // await fetch(`http://localhost:${server.address().port}`, { + // keepalive: false, + // headers: { 'accept-encoding': 'deflate, gzip' } + // }) + // } catch { } + // }) test('content-encoding header', async (t) => { - const { strictEqual } = tspl(t, { plan: 3 }) - const response = await fetch(`http://localhost:${server.address().port}`, { keepalive: false, headers: { 'accept-encoding': 'deflate, gzip' } @@ -74,13 +72,9 @@ describe('content-encoding handling', () => { strictEqual(response.headers.get('content-encoding'), 'deflate, gzip') strictEqual(response.headers.get('content-type'), 'text/plain') strictEqual(await response.text(), 'Hello, World!') - - await t.completed }) test('content-encoding header is case-iNsENsITIve', async (t) => { - const { strictEqual } = tspl(t, { plan: 3 }) - const response = await fetch(`http://localhost:${server.address().port}`, { keepalive: false, headers: { 'accept-encoding': 'DeFlAtE, GzIp' } @@ -89,15 +83,11 @@ describe('content-encoding handling', () => { strictEqual(response.headers.get('content-encoding'), 'deflate, gzip') strictEqual(response.headers.get('content-type'), 'text/plain') strictEqual(await response.text(), 'Hello, World!') - - await t.completed }) test('should decompress zstandard response', { skip: typeof require('node:zlib').createZstdDecompress !== 'function' }, - async (t) => { - const { strictEqual } = tspl(t, { plan: 3 }) - + async () => { const response = await fetch(`http://localhost:${server.address().port}`, { keepalive: false, headers: { 'accept-encoding': 'zstd' } @@ -106,7 +96,5 @@ describe('content-encoding handling', () => { strictEqual(response.headers.get('content-encoding'), 'zstd') strictEqual(response.headers.get('content-type'), 'text/plain') strictEqual(await response.text(), 'Hello, World!') - - await t.completed }) }) From 234c00f4e24feb005c04ca43af93cc0f88a5aef2 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 13 Sep 2025 01:38:14 +0200 Subject: [PATCH 4/8] eat this --- test/fetch/cookies.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index 19785d3eab8..4af991af8e8 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -36,12 +36,14 @@ describe('cookies', () => { const response = await fetch(`http://localhost:${server.address().port}?${query}`) strictEqual(response.headers.get('set-cookie'), 'name=value; Domain=example.com') + strictEqual(await response.text(), '') const response2 = await fetch(`http://localhost:${server.address().port}?${query}`, { credentials: 'include' }) strictEqual(response2.headers.get('set-cookie'), 'name=value; Domain=example.com') + strictEqual(await response2.text(), '') }) test('Can send cookies to a server with fetch - issue #1463', async () => { @@ -82,8 +84,7 @@ describe('cookies', () => { stream.end('test') }) - server.listen(0) - await once(server, 'listening') + await once(server.listen(0), 'listening') const client = new Client(`https://localhost:${server.address().port}`, { connect: { From 4011b8d39929df64500df43b62cb658fa9890927 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 13 Sep 2025 01:44:55 +0200 Subject: [PATCH 5/8] cookie --- test/fetch/cookies.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index 4af991af8e8..e810e88e6a5 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -8,6 +8,7 @@ const { stringify: qsStringify } = require('node:querystring') const { Client, fetch, Headers } = require('../..') const pem = require('@metcoder95/https-pem') const { createSecureServer } = require('node:http2') +const { createDeferredPromise } = require('../../lib/util/promise') describe('cookies', () => { let server @@ -72,6 +73,7 @@ describe('cookies', () => { }) test('Can receive set-cookie headers from a http2 server using fetch - issue #2885', async () => { + const donePromise = createDeferredPromise() const server = createSecureServer(pem) server.on('stream', (stream, headers) => { stream.respond({ @@ -82,6 +84,7 @@ describe('cookies', () => { }) stream.end('test') + donePromise.resolve() }) await once(server.listen(0), 'listening') @@ -107,6 +110,7 @@ describe('cookies', () => { deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) + await donePromise.promise await client.close() server.close() await once(server, 'close') From fb9e3bfaf2eb0671019f4fbac18a6770c0ec9ba8 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 13 Sep 2025 02:16:32 +0200 Subject: [PATCH 6/8] fix --- test/fetch/cookies.js | 8 +++++--- test/fetch/encoding.js | 9 --------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index e810e88e6a5..9ced0572c7b 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -96,6 +96,11 @@ describe('cookies', () => { allowH2: true }) + after(async () => { + await client.close() + await new Promise((resolve, reject) => server.close(err => err ? reject(err) : resolve())) + }) + const response = await fetch( `https://localhost:${server.address().port}/`, // Needs to be passed to disable the reject unauthorized @@ -111,8 +116,5 @@ describe('cookies', () => { deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) await donePromise.promise - await client.close() - server.close() - await once(server, 'close') }) }) diff --git a/test/fetch/encoding.js b/test/fetch/encoding.js index 3132ab9ed26..9ba0a6f6ca4 100644 --- a/test/fetch/encoding.js +++ b/test/fetch/encoding.js @@ -54,15 +54,6 @@ describe('content-encoding handling', () => { server.close() }) - // test('warmup', async (t) => { - // try { - // await fetch(`http://localhost:${server.address().port}`, { - // keepalive: false, - // headers: { 'accept-encoding': 'deflate, gzip' } - // }) - // } catch { } - // }) - test('content-encoding header', async (t) => { const response = await fetch(`http://localhost:${server.address().port}`, { keepalive: false, From 33f7fb42f78a274ce5e7202918001e6bd78a5110 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 13 Sep 2025 02:37:50 +0200 Subject: [PATCH 7/8] await the text --- test/fetch/cookies.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index 9ced0572c7b..8ca21e9e4cf 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -114,6 +114,7 @@ describe('cookies', () => { ) deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) + strictEqual(await response.text(), 'test') await donePromise.promise }) From f4cc9a5c323bb3ba0b3b39beac77167c488a242d Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 13 Sep 2025 02:44:07 +0200 Subject: [PATCH 8/8] fix remarks --- test/fetch/cookies.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/fetch/cookies.js b/test/fetch/cookies.js index 8ca21e9e4cf..25d2838315a 100644 --- a/test/fetch/cookies.js +++ b/test/fetch/cookies.js @@ -8,7 +8,6 @@ const { stringify: qsStringify } = require('node:querystring') const { Client, fetch, Headers } = require('../..') const pem = require('@metcoder95/https-pem') const { createSecureServer } = require('node:http2') -const { createDeferredPromise } = require('../../lib/util/promise') describe('cookies', () => { let server @@ -73,7 +72,6 @@ describe('cookies', () => { }) test('Can receive set-cookie headers from a http2 server using fetch - issue #2885', async () => { - const donePromise = createDeferredPromise() const server = createSecureServer(pem) server.on('stream', (stream, headers) => { stream.respond({ @@ -84,7 +82,6 @@ describe('cookies', () => { }) stream.end('test') - donePromise.resolve() }) await once(server.listen(0), 'listening') @@ -96,11 +93,6 @@ describe('cookies', () => { allowH2: true }) - after(async () => { - await client.close() - await new Promise((resolve, reject) => server.close(err => err ? reject(err) : resolve())) - }) - const response = await fetch( `https://localhost:${server.address().port}/`, // Needs to be passed to disable the reject unauthorized @@ -116,6 +108,7 @@ describe('cookies', () => { deepStrictEqual(response.headers.getSetCookie(), ['Space=Cat; Secure; HttpOnly']) strictEqual(await response.text(), 'test') - await donePromise.promise + await client.close() + await new Promise((resolve, reject) => server.close(err => err ? reject(err) : resolve())) }) })