Skip to content

Commit 1ca23ce

Browse files
committed
fix: ignore middleware rewrite when redirecting
The Next.js behaviour is for a middleware redirect to take precedence over a middleware rewrite when both are present at once.
1 parent 733a021 commit 1ca23ce

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

edge-runtime/lib/response.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ export const buildResponse = async ({
116116
const res = new Response(result.response.body, result.response)
117117
request.headers.set('x-nf-next-middleware', 'skip')
118118

119-
let rewrite = res.headers.get('x-middleware-rewrite')
120119
let redirect = res.headers.get('location')
121120
let nextRedirect = res.headers.get('x-nextjs-redirect')
121+
// If we have both a redirect and a rewrite, the redirect must take precedence
122+
let rewrite = !redirect && !nextRedirect ? res.headers.get('x-middleware-rewrite') : false
122123

123124
// Data requests (i.e. requests for /_next/data ) need special handling
124125
const isDataReq = request.headers.has('x-nextjs-data')

tests/fixtures/middleware/middleware.ts

+10
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ const getResponse = (request: NextRequest) => {
8080
})
8181
}
8282

83+
if (request.nextUrl.pathname === '/test/rewrite-and-redirect') {
84+
return NextResponse.redirect(new URL('/other', request.url), {
85+
status: 302,
86+
statusText: 'Found',
87+
headers: {
88+
'x-middleware-rewrite': new URL('/test/should-not-be-rewritten', request.url).toString(),
89+
},
90+
})
91+
}
92+
8393
return NextResponse.json({ error: 'Error' }, { status: 500 })
8494
}
8595

tests/integration/edge-handler.test.ts

+26-4
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe('redirect', () => {
8888
expect(response.status).toBe(307)
8989
expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string')
9090
expect(
91-
new URL(response.headers.get('location') as string).pathname,
91+
new URL(response.headers.get('location')!).pathname,
9292
'redirected to the correct path',
9393
).toEqual('/other')
9494
expect(origin.calls).toBe(0)
@@ -111,12 +111,34 @@ describe('redirect', () => {
111111
expect(response.status).toBe(307)
112112
expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string')
113113
expect(
114-
new URL(response.headers.get('location') as string).pathname,
114+
new URL(response.headers.get('location')!).pathname,
115115
'redirected to the correct path',
116116
).toEqual('/other')
117117
expect(response.headers.get('x-header-from-redirect'), 'hello').toBe('hello')
118118
expect(origin.calls).toBe(0)
119119
})
120+
121+
test<FixtureTestContext>('should ignore x-middleware-rewrite when redirecting', async (ctx) => {
122+
await createFixture('middleware', ctx)
123+
await runPlugin(ctx)
124+
125+
const origin = new LocalServer()
126+
const response = await invokeEdgeFunction(ctx, {
127+
functions: ['___netlify-edge-handler-middleware'],
128+
origin,
129+
redirect: 'manual',
130+
url: '/test/rewrite-and-redirect',
131+
})
132+
133+
ctx.cleanup?.push(() => origin.stop())
134+
135+
expect(response.status).toBe(302)
136+
expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string')
137+
expect(
138+
new URL(response.headers.get('location')!).pathname,
139+
'redirected to the correct path',
140+
).toEqual('/other')
141+
})
120142
})
121143

122144
describe('rewrite', () => {
@@ -309,7 +331,7 @@ describe('should run middleware on data requests', () => {
309331
expect(response.status).toBe(307)
310332
expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string')
311333
expect(
312-
new URL(response.headers.get('location') as string).pathname,
334+
new URL(response.headers.get('location')!).pathname,
313335
'redirected to the correct path',
314336
).toEqual('/other')
315337
expect(response.headers.get('x-header-from-redirect'), 'hello').toBe('hello')
@@ -333,7 +355,7 @@ describe('should run middleware on data requests', () => {
333355
expect(response.status).toBe(307)
334356
expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string')
335357
expect(
336-
new URL(response.headers.get('location') as string).pathname,
358+
new URL(response.headers.get('location')!).pathname,
337359
'redirected to the correct path',
338360
).toEqual('/other')
339361
expect(response.headers.get('x-header-from-redirect'), 'hello').toBe('hello')

0 commit comments

Comments
 (0)