Skip to content

Commit 8ca76ab

Browse files
authored
fix(interceptor): add throwOnMaxRedirect to types and interceptor opts (#5066)
1 parent 332a3b6 commit 8ca76ab

5 files changed

Lines changed: 55 additions & 4 deletions

File tree

lib/handler/redirect-handler.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ class RedirectHandler {
2323
throw new InvalidArgumentError('maxRedirections must be a positive number')
2424
}
2525

26+
if (opts.throwOnMaxRedirect != null && typeof opts.throwOnMaxRedirect !== 'boolean') {
27+
throw new InvalidArgumentError('throwOnMaxRedirect must be a boolean')
28+
}
29+
2630
this.dispatch = dispatch
2731
this.location = null
2832
const { maxRedirections: _, ...cleanOpts } = opts

lib/interceptor/redirect.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
const RedirectHandler = require('../handler/redirect-handler')
44

5-
function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections } = {}) {
5+
function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections, throwOnMaxRedirect: defaultThrowOnMaxRedirect } = {}) {
66
return (dispatch) => {
77
return function Intercept (opts, handler) {
8-
const { maxRedirections = defaultMaxRedirections, ...rest } = opts
8+
const { maxRedirections = defaultMaxRedirections, throwOnMaxRedirect = defaultThrowOnMaxRedirect, ...rest } = opts
99

1010
if (maxRedirections == null || maxRedirections === 0) {
1111
return dispatch(opts, handler)
1212
}
1313

14-
const dispatchOpts = { ...rest } // Stop sub dispatcher from also redirecting.
14+
const dispatchOpts = { ...rest, throwOnMaxRedirect } // Stop sub dispatcher from also redirecting.
1515
const redirectHandler = new RedirectHandler(dispatch, maxRedirections, dispatchOpts, handler)
1616
return dispatch(dispatchOpts, redirectHandler)
1717
}

test/interceptors/redirect.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,43 @@ for (const factory of [
466466
await t.completed
467467
})
468468

469+
test('should throw when max redirections is reached and throwOnMaxRedirect is set as interceptor default', async t => {
470+
t = tspl(t, { plan: 1 })
471+
472+
const server = await startRedirectingServer()
473+
474+
const dispatcher = new undici.Agent().compose(
475+
redirect({ maxRedirections: 2, throwOnMaxRedirect: true })
476+
)
477+
after(() => dispatcher.close())
478+
479+
try {
480+
await undici.request(`http://${server}/300`, { dispatcher })
481+
t.fail('Did not throw')
482+
} catch (error) {
483+
t.strictEqual(error.message, 'max redirects')
484+
}
485+
486+
await t.completed
487+
})
488+
489+
test('should not allow invalid throwOnMaxRedirect arguments', async t => {
490+
t = tspl(t, { plan: 1 })
491+
492+
try {
493+
await request(t, 'localhost', undefined, 'http://localhost', {
494+
method: 'GET',
495+
maxRedirections: 1,
496+
throwOnMaxRedirect: 'INVALID'
497+
})
498+
t.fail('Did not throw')
499+
} catch (err) {
500+
t.strictEqual(err.message, 'throwOnMaxRedirect must be a boolean')
501+
}
502+
503+
await t.completed
504+
})
505+
469506
test('when a Location response header is NOT present', async t => {
470507
t = tspl(t, { plan: 6 * 3 })
471508

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { expectAssignable, expectNotAssignable } from 'tsd'
2+
import Interceptors from '../../types/interceptors'
3+
4+
expectAssignable<Interceptors.RedirectInterceptorOpts>({})
5+
expectAssignable<Interceptors.RedirectInterceptorOpts>({ maxRedirections: 3 })
6+
expectAssignable<Interceptors.RedirectInterceptorOpts>({ throwOnMaxRedirect: true })
7+
expectAssignable<Interceptors.RedirectInterceptorOpts>({ maxRedirections: 3, throwOnMaxRedirect: true })
8+
9+
expectNotAssignable<Interceptors.RedirectInterceptorOpts>({ maxRedirections: 'INVALID' })
10+
expectNotAssignable<Interceptors.RedirectInterceptorOpts>({ throwOnMaxRedirect: 'INVALID' })

types/interceptors.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default Interceptors
88
declare namespace Interceptors {
99
export type DumpInterceptorOpts = { maxSize?: number }
1010
export type RetryInterceptorOpts = RetryHandler.RetryOptions
11-
export type RedirectInterceptorOpts = { maxRedirections?: number }
11+
export type RedirectInterceptorOpts = { maxRedirections?: number, throwOnMaxRedirect?: boolean }
1212
export type DecompressInterceptorOpts = {
1313
skipErrorResponses?: boolean
1414
skipStatusCodes?: number[]

0 commit comments

Comments
 (0)