diff --git a/lib/fetch/index.js b/lib/fetch/index.js index 17c3d87ea62..dea206965a9 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -1203,6 +1203,9 @@ function httpRedirectFetch (fetchParams, response) { // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name request.headersList.delete('authorization') + // https://fetch.spec.whatwg.org/#authentication-entries + request.headersList.delete('proxy-authorization', true) + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. request.headersList.delete('cookie') request.headersList.delete('host') diff --git a/package.json b/package.json index 2b64daf41e2..15a94360d8d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "5.28.2", + "version": "5.28.3", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { diff --git a/test/fetch/redirect-cross-origin-header.js b/test/fetch/redirect-cross-origin-header.js index fca48c44ea0..8c3e674968b 100644 --- a/test/fetch/redirect-cross-origin-header.js +++ b/test/fetch/redirect-cross-origin-header.js @@ -6,11 +6,12 @@ const { once } = require('events') const { fetch } = require('../..') test('Cross-origin redirects clear forbidden headers', async (t) => { - t.plan(5) + t.plan(6) const server1 = createServer((req, res) => { t.equal(req.headers.cookie, undefined) t.equal(req.headers.authorization, undefined) + t.equal(req.headers['proxy-authorization'], undefined) res.end('redirected') }).listen(0) @@ -39,7 +40,8 @@ test('Cross-origin redirects clear forbidden headers', async (t) => { const res = await fetch(`http://localhost:${server2.address().port}`, { headers: { Authorization: 'test', - Cookie: 'ddd=dddd' + Cookie: 'ddd=dddd', + 'Proxy-Authorization': 'test' } }) diff --git a/test/mock-interceptor-unused-assertions.js b/test/mock-interceptor-unused-assertions.js index bfa2275777f..2fe8b824f9f 100644 --- a/test/mock-interceptor-unused-assertions.js +++ b/test/mock-interceptor-unused-assertions.js @@ -3,6 +3,11 @@ const { test, beforeEach, afterEach } = require('tap') const { MockAgent, setGlobalDispatcher } = require('..') const PendingInterceptorsFormatter = require('../lib/mock/pending-interceptors-formatter') +const util = require('../lib/core/util') + +// Since Node.js v21 `console.table` rows are aligned to the left +// https://github.com/nodejs/node/pull/50135 +const tableRowsAlignedToLeft = util.nodeMajor >= 21 || (util.nodeMajor === 20 && util.nodeMinor >= 11) // Avoid colors in the output for inline snapshots. const pendingInterceptorsFormatter = new PendingInterceptorsFormatter({ disableColors: true }) @@ -40,7 +45,17 @@ test('1 pending interceptor', t => { const err = t.throws(() => mockAgentWithOneInterceptor().assertNoPendingInterceptors({ pendingInterceptorsFormatter })) - t.same(err.message, ` + t.same(err.message, tableRowsAlignedToLeft + ? ` +1 interceptor is pending: + +┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐ +│ (index) │ Method │ Origin │ Path │ Status code │ Persistent │ Invocations │ Remaining │ +├─────────┼────────┼───────────────────────┼──────┼─────────────┼────────────┼─────────────┼───────────┤ +│ 0 │ 'GET' │ 'https://example.com' │ '/' │ 200 │ '❌' │ 0 │ 1 │ +└─────────┴────────┴───────────────────────┴──────┴─────────────┴────────────┴─────────────┴───────────┘ +`.trim() + : ` 1 interceptor is pending: ┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -61,7 +76,18 @@ test('2 pending interceptors', t => { .reply(204, 'OK') const err = t.throws(() => withTwoInterceptors.assertNoPendingInterceptors({ pendingInterceptorsFormatter })) - t.same(err.message, ` + t.same(err.message, tableRowsAlignedToLeft + ? ` +2 interceptors are pending: + +┌─────────┬────────┬──────────────────────────┬──────────────┬─────────────┬────────────┬─────────────┬───────────┐ +│ (index) │ Method │ Origin │ Path │ Status code │ Persistent │ Invocations │ Remaining │ +├─────────┼────────┼──────────────────────────┼──────────────┼─────────────┼────────────┼─────────────┼───────────┤ +│ 0 │ 'GET' │ 'https://example.com' │ '/' │ 200 │ '❌' │ 0 │ 1 │ +│ 1 │ 'GET' │ 'https://localhost:9999' │ '/some/path' │ 204 │ '❌' │ 0 │ 1 │ +└─────────┴────────┴──────────────────────────┴──────────────┴─────────────┴────────────┴─────────────┴───────────┘ +`.trim() + : ` 2 interceptors are pending: ┌─────────┬────────┬──────────────────────────┬──────────────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -123,7 +149,20 @@ test('Variations of persist(), times(), and pending status', async t => { const err = t.throws(() => agent.assertNoPendingInterceptors({ pendingInterceptorsFormatter })) - t.same(err.message, ` + t.same(err.message, tableRowsAlignedToLeft + ? ` +4 interceptors are pending: + +┌─────────┬────────┬──────────────────────────┬──────────────────────┬─────────────┬────────────┬─────────────┬───────────┐ +│ (index) │ Method │ Origin │ Path │ Status code │ Persistent │ Invocations │ Remaining │ +├─────────┼────────┼──────────────────────────┼──────────────────────┼─────────────┼────────────┼─────────────┼───────────┤ +│ 0 │ 'GET' │ 'https://example.com' │ '/' │ 200 │ '❌' │ 0 │ 1 │ +│ 1 │ 'GET' │ 'https://localhost:9999' │ '/persistent/unused' │ 200 │ '✅' │ 0 │ Infinity │ +│ 2 │ 'GET' │ 'https://localhost:9999' │ '/times/partial' │ 200 │ '❌' │ 1 │ 4 │ +│ 3 │ 'GET' │ 'https://localhost:9999' │ '/times/unused' │ 200 │ '❌' │ 0 │ 2 │ +└─────────┴────────┴──────────────────────────┴──────────────────────┴─────────────┴────────────┴─────────────┴───────────┘ +`.trim() + : ` 4 interceptors are pending: ┌─────────┬────────┬──────────────────────────┬──────────────────────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -172,7 +211,17 @@ test('defaults to rendering output with terminal color when process.env.CI is un const err = t.throws( () => mockAgentWithOneInterceptor().assertNoPendingInterceptors()) - t.same(err.message, ` + t.same(err.message, tableRowsAlignedToLeft + ? ` +1 interceptor is pending: + +┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐ +│ (index) │ Method │ Origin │ Path │ Status code │ Persistent │ Invocations │ Remaining │ +├─────────┼────────┼───────────────────────┼──────┼─────────────┼────────────┼─────────────┼───────────┤ +│ 0 │ \u001b[32m'GET'\u001b[39m │ \u001b[32m'https://example.com'\u001b[39m │ \u001b[32m'/'\u001b[39m │ \u001b[33m200\u001b[39m │ \u001b[32m'❌'\u001b[39m │ \u001b[33m0\u001b[39m │ \u001b[33m1\u001b[39m │ +└─────────┴────────┴───────────────────────┴──────┴─────────────┴────────────┴─────────────┴───────────┘ +`.trim() + : ` 1 interceptor is pending: ┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐