From 43dab4575fcef5597c02da7c82eb26237e056cf1 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 11 May 2026 07:24:13 +0000 Subject: [PATCH 1/3] add redirect header stripping option --- docs/docs/api/Dispatcher.md | 6 ++++ docs/docs/api/RedirectHandler.md | 4 ++- lib/handler/redirect-handler.js | 36 +++++++++++++++---- lib/interceptor/redirect.js | 6 ++-- test/interceptors/redirect.js | 42 +++++++++++++++++++++++ test/types/redirect-interceptor.test-d.ts | 4 +++ types/interceptors.d.ts | 2 +- 7 files changed, 89 insertions(+), 11 deletions(-) diff --git a/docs/docs/api/Dispatcher.md b/docs/docs/api/Dispatcher.md index b1674b3092a..65c4730fef2 100644 --- a/docs/docs/api/Dispatcher.md +++ b/docs/docs/api/Dispatcher.md @@ -991,6 +991,12 @@ The `redirect` interceptor allows you to customize the way your dispatcher handl It accepts the same arguments as the [`RedirectHandler` constructor](/docs/docs/api/RedirectHandler.md). +Options: + +- **maxRedirections** `number` - Maximum number of redirections allowed. +- **throwOnMaxRedirect** `boolean` - Throw when the maximum number of redirections is reached. +- **stripHeadersOnRedirect** `string[]` - Header names to remove from redirected requests. + **Example - Basic Redirect Interceptor** ```js diff --git a/docs/docs/api/RedirectHandler.md b/docs/docs/api/RedirectHandler.md index d1dd9d993f9..b373401bc01 100644 --- a/docs/docs/api/RedirectHandler.md +++ b/docs/docs/api/RedirectHandler.md @@ -8,7 +8,7 @@ Arguments: - **dispatch** `function` - The dispatch function to be called after every retry. - **maxRedirections** `number` - Maximum number of redirections allowed. -- **opts** `object` - Options for handling redirection. +- **opts** `object` - Options for handling redirection. Supports `throwOnMaxRedirect` and `stripHeadersOnRedirect`. - **handler** `object` - An object containing handlers for different stages of the request lifecycle. Returns: `RedirectHandler` @@ -18,6 +18,8 @@ Returns: `RedirectHandler` - **dispatch** `(options: Dispatch.DispatchOptions, handlers: Dispatch.DispatchHandler) => Promise` (required) - Dispatch function to be called after every redirection. - **maxRedirections** `number` (required) - Maximum number of redirections allowed. - **opts** `object` (required) - Options for handling redirection. + - **throwOnMaxRedirect** `boolean` - Throw when the maximum number of redirections is reached. + - **stripHeadersOnRedirect** `string[]` - Header names to remove from redirected requests. - **handler** `object` (required) - Handlers for different stages of the request lifecycle. ### Properties diff --git a/lib/handler/redirect-handler.js b/lib/handler/redirect-handler.js index 35a4aa4232e..89124bc2455 100644 --- a/lib/handler/redirect-handler.js +++ b/lib/handler/redirect-handler.js @@ -27,11 +27,16 @@ class RedirectHandler { throw new InvalidArgumentError('throwOnMaxRedirect must be a boolean') } + if (opts.stripHeadersOnRedirect != null && !Array.isArray(opts.stripHeadersOnRedirect)) { + throw new InvalidArgumentError('stripHeadersOnRedirect must be an array') + } + this.dispatch = dispatch this.location = null - const { maxRedirections: _, ...cleanOpts } = opts + const { maxRedirections: _, stripHeadersOnRedirect, ...cleanOpts } = opts this.opts = cleanOpts // opts must be a copy, exclude maxRedirections this.opts.body = util.wrapRequestBody(this.opts.body) + this.stripHeadersOnRedirect = normalizeStripHeadersOnRedirect(stripHeadersOnRedirect) this.maxRedirections = maxRedirections this.handler = handler this.history = [] @@ -100,7 +105,7 @@ class RedirectHandler { // Remove headers referring to the original URL. // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. // https://tools.ietf.org/html/rfc7231#section-6.4 - this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin, this.stripHeadersOnRedirect) this.opts.path = path this.opts.origin = origin this.opts.query = null @@ -152,10 +157,13 @@ class RedirectHandler { } // https://tools.ietf.org/html/rfc7231#section-6.4.4 -function shouldRemoveHeader (header, removeContent, unknownOrigin) { +function shouldRemoveHeader (header, removeContent, unknownOrigin, stripHeaders) { if (header.length === 4) { return util.headerNameToString(header) === 'host' } + if (stripHeaders?.has(util.headerNameToString(header))) { + return true + } if (removeContent && util.headerNameToString(header).startsWith('content-')) { return true } @@ -167,11 +175,27 @@ function shouldRemoveHeader (header, removeContent, unknownOrigin) { } // https://tools.ietf.org/html/rfc7231#section-6.4 -function cleanRequestHeaders (headers, removeContent, unknownOrigin) { +function normalizeStripHeadersOnRedirect (headers) { + if (headers == null) { + return null + } + + const normalized = new Set() + for (const header of headers) { + if (typeof header !== 'string') { + throw new InvalidArgumentError('stripHeadersOnRedirect must contain header names') + } + + normalized.add(util.headerNameToString(header)) + } + return normalized +} + +function cleanRequestHeaders (headers, removeContent, unknownOrigin, stripHeaders) { const ret = [] if (Array.isArray(headers)) { for (let i = 0; i < headers.length; i += 2) { - if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin, stripHeaders)) { ret.push(headers[i], headers[i + 1]) } } @@ -179,7 +203,7 @@ function cleanRequestHeaders (headers, removeContent, unknownOrigin) { const entries = util.hasSafeIterator(headers) ? headers : Object.entries(headers) for (const [key, value] of entries) { - if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin, stripHeaders)) { ret.push(key, value) } } diff --git a/lib/interceptor/redirect.js b/lib/interceptor/redirect.js index 83b4c9a7b2f..227557494a2 100644 --- a/lib/interceptor/redirect.js +++ b/lib/interceptor/redirect.js @@ -2,16 +2,16 @@ const RedirectHandler = require('../handler/redirect-handler') -function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections, throwOnMaxRedirect: defaultThrowOnMaxRedirect } = {}) { +function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections, throwOnMaxRedirect: defaultThrowOnMaxRedirect, stripHeadersOnRedirect: defaultStripHeadersOnRedirect } = {}) { return (dispatch) => { return function Intercept (opts, handler) { - const { maxRedirections = defaultMaxRedirections, throwOnMaxRedirect = defaultThrowOnMaxRedirect, ...rest } = opts + const { maxRedirections = defaultMaxRedirections, throwOnMaxRedirect = defaultThrowOnMaxRedirect, stripHeadersOnRedirect = defaultStripHeadersOnRedirect, ...rest } = opts if (maxRedirections == null || maxRedirections === 0) { return dispatch(opts, handler) } - const dispatchOpts = { ...rest, throwOnMaxRedirect } // Stop sub dispatcher from also redirecting. + const dispatchOpts = { ...rest, throwOnMaxRedirect, stripHeadersOnRedirect } // Stop sub dispatcher from also redirecting. const redirectHandler = new RedirectHandler(dispatch, maxRedirections, dispatchOpts, handler) return dispatch(dispatchOpts, redirectHandler) } diff --git a/test/interceptors/redirect.js b/test/interceptors/redirect.js index cabe5c1f47f..813fc02f58a 100644 --- a/test/interceptors/redirect.js +++ b/test/interceptors/redirect.js @@ -856,6 +856,48 @@ test('same-origin redirect preserves plain object headers with polluted Object.p } }) +test('same-origin redirects strip configured headers', async (t) => { + const { strictEqual } = tspl(t, { plan: 5 }) + + const server = createServer((req, res) => { + if (req.url === '/redirect') { + strictEqual(req.headers['x-custom'], 'secret') + strictEqual(req.headers['x-keep'], 'present') + + res.writeHead(302, { + Location: '/final' + }) + res.end() + return + } + + strictEqual(req.headers['x-custom'], undefined) + strictEqual(req.headers['x-keep'], 'present') + res.end('redirected') + }).listen(0) + + after(() => server.close()) + + await once(server, 'listening') + + const dispatcher = new undici.Agent({}).compose(redirect({ + maxRedirections: 1, + stripHeadersOnRedirect: ['X-Custom'] + })) + after(() => dispatcher.close()) + + const res = await undici.request(`http://localhost:${server.address().port}/redirect`, { + dispatcher, + headers: { + 'X-Custom': 'secret', + 'X-Keep': 'present' + } + }) + + const text = await res.body.text() + strictEqual(text, 'redirected') +}) + test('Cross-origin redirects clear forbidden headers', async (t) => { const { strictEqual } = tspl(t, { plan: 6 }) diff --git a/test/types/redirect-interceptor.test-d.ts b/test/types/redirect-interceptor.test-d.ts index 42612e0dec7..79c3a581bf0 100644 --- a/test/types/redirect-interceptor.test-d.ts +++ b/test/types/redirect-interceptor.test-d.ts @@ -5,6 +5,10 @@ expectAssignable({}) expectAssignable({ maxRedirections: 3 }) expectAssignable({ throwOnMaxRedirect: true }) expectAssignable({ maxRedirections: 3, throwOnMaxRedirect: true }) +expectAssignable({ stripHeadersOnRedirect: ['x-custom'] }) +expectAssignable({ maxRedirections: 3, stripHeadersOnRedirect: ['x-custom'] }) expectNotAssignable({ maxRedirections: 'INVALID' }) expectNotAssignable({ throwOnMaxRedirect: 'INVALID' }) +expectNotAssignable({ stripHeadersOnRedirect: 'INVALID' }) +expectNotAssignable({ stripHeadersOnRedirect: [1] }) diff --git a/types/interceptors.d.ts b/types/interceptors.d.ts index 3b90a28592f..25139e7c952 100644 --- a/types/interceptors.d.ts +++ b/types/interceptors.d.ts @@ -8,7 +8,7 @@ export default Interceptors declare namespace Interceptors { export type DumpInterceptorOpts = { maxSize?: number } export type RetryInterceptorOpts = RetryHandler.RetryOptions - export type RedirectInterceptorOpts = { maxRedirections?: number, throwOnMaxRedirect?: boolean } + export type RedirectInterceptorOpts = { maxRedirections?: number, throwOnMaxRedirect?: boolean, stripHeadersOnRedirect?: string[] } export type DecompressInterceptorOpts = { skipErrorResponses?: boolean skipStatusCodes?: number[] From d8cb0d18f787b2e6e1548c0011fdcf272cc1e612 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 11 May 2026 07:42:48 +0000 Subject: [PATCH 2/3] test: import after in parser issues --- test/parser-issues.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parser-issues.js b/test/parser-issues.js index 4e398cdba01..3371eda682a 100644 --- a/test/parser-issues.js +++ b/test/parser-issues.js @@ -1,7 +1,7 @@ 'use strict' const { tspl } = require('@matteo.collina/tspl') -const { test } = require('node:test') +const { test, after } = require('node:test') const net = require('node:net') const { Client, errors, fetch } = require('..') From 48d84f70abb7b444c38014092c1912a9d198328f Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 11 May 2026 10:09:37 +0000 Subject: [PATCH 3/3] add cross-origin redirect header stripping --- docs/docs/api/Dispatcher.md | 3 +- docs/docs/api/RedirectHandler.md | 5 +- lib/handler/redirect-handler.js | 39 +++++++-------- lib/interceptor/redirect.js | 6 +-- test/interceptors/redirect.js | 58 +++++++++++++++++++++++ test/types/redirect-interceptor.test-d.ts | 4 ++ types/interceptors.d.ts | 2 +- 7 files changed, 91 insertions(+), 26 deletions(-) diff --git a/docs/docs/api/Dispatcher.md b/docs/docs/api/Dispatcher.md index 65c4730fef2..2137e174a8a 100644 --- a/docs/docs/api/Dispatcher.md +++ b/docs/docs/api/Dispatcher.md @@ -995,7 +995,8 @@ Options: - **maxRedirections** `number` - Maximum number of redirections allowed. - **throwOnMaxRedirect** `boolean` - Throw when the maximum number of redirections is reached. -- **stripHeadersOnRedirect** `string[]` - Header names to remove from redirected requests. +- **stripHeadersOnRedirect** `string[]` - Header names to remove from all redirected requests. +- **stripHeadersOnCrossOriginRedirect** `string[]` - Header names to remove from cross-origin redirected requests. **Example - Basic Redirect Interceptor** diff --git a/docs/docs/api/RedirectHandler.md b/docs/docs/api/RedirectHandler.md index b373401bc01..5d49653be0d 100644 --- a/docs/docs/api/RedirectHandler.md +++ b/docs/docs/api/RedirectHandler.md @@ -8,7 +8,7 @@ Arguments: - **dispatch** `function` - The dispatch function to be called after every retry. - **maxRedirections** `number` - Maximum number of redirections allowed. -- **opts** `object` - Options for handling redirection. Supports `throwOnMaxRedirect` and `stripHeadersOnRedirect`. +- **opts** `object` - Options for handling redirection. Supports `throwOnMaxRedirect`, `stripHeadersOnRedirect`, and `stripHeadersOnCrossOriginRedirect`. - **handler** `object` - An object containing handlers for different stages of the request lifecycle. Returns: `RedirectHandler` @@ -19,7 +19,8 @@ Returns: `RedirectHandler` - **maxRedirections** `number` (required) - Maximum number of redirections allowed. - **opts** `object` (required) - Options for handling redirection. - **throwOnMaxRedirect** `boolean` - Throw when the maximum number of redirections is reached. - - **stripHeadersOnRedirect** `string[]` - Header names to remove from redirected requests. + - **stripHeadersOnRedirect** `string[]` - Header names to remove from all redirected requests. + - **stripHeadersOnCrossOriginRedirect** `string[]` - Header names to remove from cross-origin redirected requests. - **handler** `object` (required) - Handlers for different stages of the request lifecycle. ### Properties diff --git a/lib/handler/redirect-handler.js b/lib/handler/redirect-handler.js index 89124bc2455..8ead972b742 100644 --- a/lib/handler/redirect-handler.js +++ b/lib/handler/redirect-handler.js @@ -27,16 +27,13 @@ class RedirectHandler { throw new InvalidArgumentError('throwOnMaxRedirect must be a boolean') } - if (opts.stripHeadersOnRedirect != null && !Array.isArray(opts.stripHeadersOnRedirect)) { - throw new InvalidArgumentError('stripHeadersOnRedirect must be an array') - } - this.dispatch = dispatch this.location = null - const { maxRedirections: _, stripHeadersOnRedirect, ...cleanOpts } = opts + const { maxRedirections: _, stripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect, ...cleanOpts } = opts this.opts = cleanOpts // opts must be a copy, exclude maxRedirections this.opts.body = util.wrapRequestBody(this.opts.body) - this.stripHeadersOnRedirect = normalizeStripHeadersOnRedirect(stripHeadersOnRedirect) + this.stripHeadersOnRedirect = normalizeStripHeaders(stripHeadersOnRedirect, 'stripHeadersOnRedirect') + this.stripHeadersOnCrossOriginRedirect = normalizeStripHeaders(stripHeadersOnCrossOriginRedirect, 'stripHeadersOnCrossOriginRedirect') this.maxRedirections = maxRedirections this.handler = handler this.history = [] @@ -105,7 +102,7 @@ class RedirectHandler { // Remove headers referring to the original URL. // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. // https://tools.ietf.org/html/rfc7231#section-6.4 - this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin, this.stripHeadersOnRedirect) + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin, this.stripHeadersOnRedirect, this.stripHeadersOnCrossOriginRedirect) this.opts.path = path this.opts.origin = origin this.opts.query = null @@ -157,33 +154,37 @@ class RedirectHandler { } // https://tools.ietf.org/html/rfc7231#section-6.4.4 -function shouldRemoveHeader (header, removeContent, unknownOrigin, stripHeaders) { - if (header.length === 4) { - return util.headerNameToString(header) === 'host' +function shouldRemoveHeader (header, removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin) { + const name = util.headerNameToString(header) + if (name === 'host') { + return true } - if (stripHeaders?.has(util.headerNameToString(header))) { + if (stripHeaders?.has(name) || (unknownOrigin && stripHeadersOnCrossOrigin?.has(name))) { return true } - if (removeContent && util.headerNameToString(header).startsWith('content-')) { + if (removeContent && name.startsWith('content-')) { return true } - if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { - const name = util.headerNameToString(header) + if (unknownOrigin) { return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization' } return false } // https://tools.ietf.org/html/rfc7231#section-6.4 -function normalizeStripHeadersOnRedirect (headers) { +function normalizeStripHeaders (headers, optionName) { if (headers == null) { return null } + if (!Array.isArray(headers)) { + throw new InvalidArgumentError(`${optionName} must be an array`) + } + const normalized = new Set() for (const header of headers) { if (typeof header !== 'string') { - throw new InvalidArgumentError('stripHeadersOnRedirect must contain header names') + throw new InvalidArgumentError(`${optionName} must contain header names`) } normalized.add(util.headerNameToString(header)) @@ -191,11 +192,11 @@ function normalizeStripHeadersOnRedirect (headers) { return normalized } -function cleanRequestHeaders (headers, removeContent, unknownOrigin, stripHeaders) { +function cleanRequestHeaders (headers, removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin) { const ret = [] if (Array.isArray(headers)) { for (let i = 0; i < headers.length; i += 2) { - if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin, stripHeaders)) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin)) { ret.push(headers[i], headers[i + 1]) } } @@ -203,7 +204,7 @@ function cleanRequestHeaders (headers, removeContent, unknownOrigin, stripHeader const entries = util.hasSafeIterator(headers) ? headers : Object.entries(headers) for (const [key, value] of entries) { - if (!shouldRemoveHeader(key, removeContent, unknownOrigin, stripHeaders)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin)) { ret.push(key, value) } } diff --git a/lib/interceptor/redirect.js b/lib/interceptor/redirect.js index 227557494a2..34e9b321197 100644 --- a/lib/interceptor/redirect.js +++ b/lib/interceptor/redirect.js @@ -2,16 +2,16 @@ const RedirectHandler = require('../handler/redirect-handler') -function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections, throwOnMaxRedirect: defaultThrowOnMaxRedirect, stripHeadersOnRedirect: defaultStripHeadersOnRedirect } = {}) { +function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections, throwOnMaxRedirect: defaultThrowOnMaxRedirect, stripHeadersOnRedirect: defaultStripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect: defaultStripHeadersOnCrossOriginRedirect } = {}) { return (dispatch) => { return function Intercept (opts, handler) { - const { maxRedirections = defaultMaxRedirections, throwOnMaxRedirect = defaultThrowOnMaxRedirect, stripHeadersOnRedirect = defaultStripHeadersOnRedirect, ...rest } = opts + const { maxRedirections = defaultMaxRedirections, throwOnMaxRedirect = defaultThrowOnMaxRedirect, stripHeadersOnRedirect = defaultStripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect = defaultStripHeadersOnCrossOriginRedirect, ...rest } = opts if (maxRedirections == null || maxRedirections === 0) { return dispatch(opts, handler) } - const dispatchOpts = { ...rest, throwOnMaxRedirect, stripHeadersOnRedirect } // Stop sub dispatcher from also redirecting. + const dispatchOpts = { ...rest, throwOnMaxRedirect, stripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect } // Stop sub dispatcher from also redirecting. const redirectHandler = new RedirectHandler(dispatch, maxRedirections, dispatchOpts, handler) return dispatch(dispatchOpts, redirectHandler) } diff --git a/test/interceptors/redirect.js b/test/interceptors/redirect.js index 813fc02f58a..cf0f0a815a9 100644 --- a/test/interceptors/redirect.js +++ b/test/interceptors/redirect.js @@ -898,6 +898,64 @@ test('same-origin redirects strip configured headers', async (t) => { strictEqual(text, 'redirected') }) +test('cross-origin redirects strip configured headers only across origins', async (t) => { + const { strictEqual } = tspl(t, { plan: 7 }) + + const server1 = createServer((req, res) => { + strictEqual(req.headers['x-custom'], undefined) + strictEqual(req.headers['x-keep'], 'present') + res.end('redirected') + }).listen(0) + + const server2 = createServer((req, res) => { + if (req.url === '/redirect') { + strictEqual(req.headers['x-custom'], 'secret') + strictEqual(req.headers['x-keep'], 'present') + + res.writeHead(302, { + Location: '/same-origin' + }) + res.end() + return + } + + strictEqual(req.headers['x-custom'], 'secret') + strictEqual(req.headers['x-keep'], 'present') + + res.writeHead(302, { + Location: `http://localhost:${server1.address().port}` + }) + res.end() + }).listen(0) + + t.after(() => { + server1.close() + server2.close() + }) + + await Promise.all([ + once(server1, 'listening'), + once(server2, 'listening') + ]) + + const dispatcher = new undici.Agent({}).compose(redirect({ + maxRedirections: 2, + stripHeadersOnCrossOriginRedirect: ['X-Custom'] + })) + after(() => dispatcher.close()) + + const res = await undici.request(`http://localhost:${server2.address().port}/redirect`, { + dispatcher, + headers: { + 'X-Custom': 'secret', + 'X-Keep': 'present' + } + }) + + const text = await res.body.text() + strictEqual(text, 'redirected') +}) + test('Cross-origin redirects clear forbidden headers', async (t) => { const { strictEqual } = tspl(t, { plan: 6 }) diff --git a/test/types/redirect-interceptor.test-d.ts b/test/types/redirect-interceptor.test-d.ts index 79c3a581bf0..1d4075a776b 100644 --- a/test/types/redirect-interceptor.test-d.ts +++ b/test/types/redirect-interceptor.test-d.ts @@ -7,8 +7,12 @@ expectAssignable({ throwOnMaxRedirect: tru expectAssignable({ maxRedirections: 3, throwOnMaxRedirect: true }) expectAssignable({ stripHeadersOnRedirect: ['x-custom'] }) expectAssignable({ maxRedirections: 3, stripHeadersOnRedirect: ['x-custom'] }) +expectAssignable({ stripHeadersOnCrossOriginRedirect: ['x-custom'] }) +expectAssignable({ maxRedirections: 3, stripHeadersOnCrossOriginRedirect: ['x-custom'] }) expectNotAssignable({ maxRedirections: 'INVALID' }) expectNotAssignable({ throwOnMaxRedirect: 'INVALID' }) expectNotAssignable({ stripHeadersOnRedirect: 'INVALID' }) expectNotAssignable({ stripHeadersOnRedirect: [1] }) +expectNotAssignable({ stripHeadersOnCrossOriginRedirect: 'INVALID' }) +expectNotAssignable({ stripHeadersOnCrossOriginRedirect: [1] }) diff --git a/types/interceptors.d.ts b/types/interceptors.d.ts index 25139e7c952..d21d717cec5 100644 --- a/types/interceptors.d.ts +++ b/types/interceptors.d.ts @@ -8,7 +8,7 @@ export default Interceptors declare namespace Interceptors { export type DumpInterceptorOpts = { maxSize?: number } export type RetryInterceptorOpts = RetryHandler.RetryOptions - export type RedirectInterceptorOpts = { maxRedirections?: number, throwOnMaxRedirect?: boolean, stripHeadersOnRedirect?: string[] } + export type RedirectInterceptorOpts = { maxRedirections?: number, throwOnMaxRedirect?: boolean, stripHeadersOnRedirect?: string[], stripHeadersOnCrossOriginRedirect?: string[] } export type DecompressInterceptorOpts = { skipErrorResponses?: boolean skipStatusCodes?: number[]