Skip to content

Commit

Permalink
Fix middleware catch-all rewrite case (#63254)
Browse files Browse the repository at this point in the history
This ensures we properly set the matched header when applying a
middleware skip optimization so that the client router has enough
context to finish resolving the dynamic route params.

Fixes: #59561

Closes NEXT-2803
  • Loading branch information
ijjk committed Mar 13, 2024
1 parent 02a0617 commit 8f09bc4
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/next/src/server/base-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1850,6 +1850,7 @@ export default abstract class Server<ServerOptions extends Options = Options> {
req.headers['x-middleware-prefetch'] &&
!(is404Page || pathname === '/_error')
) {
res.setHeader('x-matched-path', pathname)
res.setHeader('x-middleware-skip', '1')
res.setHeader(
'cache-control',
Expand Down
4 changes: 4 additions & 0 deletions test/e2e/middleware-rewrites/app/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const PUBLIC_FILE = /\.(.*)$/
export async function middleware(request) {
const url = request.nextUrl

if (url.pathname.includes('article')) {
return NextResponse.next()
}

// this is needed for tests to get the BUILD_ID
if (url.pathname.startsWith('/_next/static/__BUILD_ID')) {
return NextResponse.next()
Expand Down
4 changes: 4 additions & 0 deletions test/e2e/middleware-rewrites/app/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ module.exports = {
},
],
afterFiles: [
{
source: '/article/:slug*',
destination: '/detail/:slug*',
},
{
source: '/afterfiles-rewrite',
destination: '/ab-test/b',
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/middleware-rewrites/app/pages/detail/[...slug].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Link from 'next/link'
import { useRouter } from 'next/router'

export default function Detail() {
const router = useRouter()

return (
<div style={{ textAlign: 'center' }}>
<Link href="/">Home</Link>

<pre>{JSON.stringify(router.query)}</pre>
</div>
)
}
4 changes: 4 additions & 0 deletions test/e2e/middleware-rewrites/app/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export default function Home() {
<div>
<p className="title">Home Page</p>
<div />
<Link href="/article/foo/bar/123" id="to-article-rewrite">
to /article/foo/bar/123
</Link>
<div />
<Link href="/rewrite-to-ab-test">A/B test homepage</Link>
<div />
<Link
Expand Down
26 changes: 25 additions & 1 deletion test/e2e/middleware-rewrites/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { join } from 'path'
import cheerio from 'cheerio'
import webdriver from 'next-webdriver'
import { NextInstance } from 'test/lib/next-modes/base'
import { check, fetchViaHTTP } from 'next-test-utils'
import { check, fetchViaHTTP, retry } from 'next-test-utils'
import { createNext, FileRef } from 'e2e-utils'
import escapeStringRegexp from 'escape-string-regexp'
import { Request } from 'playwright'

describe('Middleware Rewrite', () => {
let next: NextInstance
Expand All @@ -23,6 +24,29 @@ describe('Middleware Rewrite', () => {
})

function tests() {
it('should handle catch-all rewrite correctly', async () => {
const browser = await next.browser('/', { waitHydration: false })

if (!(global as any).isNextDev) {
let requests = []

browser.on('request', (req: Request) => {
requests.push(new URL(req.url()).pathname)
})

browser.elementByCss('#to-article-rewrite').moveTo()

await retry(async () => {
expect(requests.some((item) => item.includes('article'))).toBe(true)
})
}

await browser.elementByCss('#to-article-rewrite').click()

const preQuery = JSON.parse(await browser.elementByCss('pre').text())
expect(preQuery).toEqual({ slug: ['foo', 'bar', '123'] })
})

it('should handle next.config.js rewrite with body correctly', async () => {
const body = JSON.stringify({ hello: 'world' })
const res = await next.fetch('/external-rewrite-body', {
Expand Down

0 comments on commit 8f09bc4

Please sign in to comment.