diff --git a/packages/nextjs/src/proxy/proxy.test.ts b/packages/nextjs/src/proxy/proxy.test.ts index 7df11e2b76..328563cc27 100644 --- a/packages/nextjs/src/proxy/proxy.test.ts +++ b/packages/nextjs/src/proxy/proxy.test.ts @@ -70,7 +70,7 @@ describe('ProxyBase', () => { Object.defineProperties(res.headers, { set: { value: (key, value) => { - res.headers[key] = value; + res.headers[key] = value; }, enumerable: false, }, @@ -677,6 +677,42 @@ describe('defineProxy', () => { }); }); + it('should stop executing proxies when a previous proxy sets location header', async () => { + const firstProxySpy = sinon.spy(); + const skippedProxySpy = sinon.spy(); + + const proxy1: ProxyHandler = { + handle: (_req, res) => { + firstProxySpy(); + return Promise.resolve(res); + }, + }; + + const redirectingProxy: ProxyHandler = { + handle: (_req, res) => { + res.headers.set('location', '/redirect-target'); + return Promise.resolve(res); + }, + }; + + const proxyAfterRedirect: ProxyHandler = { + handle: (_req, res) => { + skippedProxySpy(); + res.headers.set('after-redirect', 'true'); + return Promise.resolve(res); + }, + }; + + const req = {} as NextRequest; + + const result = await defineProxy(proxy1, redirectingProxy, proxyAfterRedirect).exec(req); + + expect(firstProxySpy).to.have.been.calledOnce; + expect(skippedProxySpy).to.not.have.been.called; + expect(result.headers.get('location')).to.equal('/redirect-target'); + expect(result.headers.get('after-redirect')).to.equal(null); + }); + it('should execute proxies with empty response', async () => { class SampleProxy extends ProxyBase { handle(_req: NextRequest, res: NextResponse) { diff --git a/packages/nextjs/src/proxy/proxy.ts b/packages/nextjs/src/proxy/proxy.ts index 82ca4e9704..68485ecd18 100644 --- a/packages/nextjs/src/proxy/proxy.ts +++ b/packages/nextjs/src/proxy/proxy.ts @@ -289,8 +289,7 @@ export const defineProxy = (...proxies: ProxyHandler[]) => { p.then((res) => { // Short-circuit the remaining proxies once a previous one // denied the request (e.g. PreviewProxy returning 403). - if (res.status === 403) return res; - + if (res.headers?.get('location') || res.status === 403) return res; return proxy.handle(req, res); }), Promise.resolve(response)