Middleware rewrites *all* dynamic routes as soon as it has rewritten one
See original GitHub issueVerify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:37 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T6000
Binaries:
Node: 16.14.2
npm: 8.5.0
Yarn: 1.22.18
pnpm: N/A
Relevant packages:
next: 12.2.1-canary.4
eslint-config-next: 12.2.0
react: 18.2.0
react-dom: 18.2.0
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
Describe the Bug
Under certain circumstances, middleware will rewrite routes which should not be rewritten. This happens only with dynamic routes in a production build.
Given the following middleware:
// /middleware.js
import { NextResponse } from "next/server";
export function middleware(request) {
return request.nextUrl.pathname.includes("page-2")
? NextResponse.rewrite(`${request.nextUrl.origin}/insufficient-access`)
: NextResponse.next();
}
And the following page:
// /pages/directory/[param].js
export async function getServerSideProps(context) {
const { page } = context.params;
return { props: { page } };
}
export default function Page({ page }) {
return <p>Hello {page}</p>;
}
Then, with client-side routing:
- visiting
/directory/page-1
will render the correct page - visiting
/directory/page-2
will render theinsufficient-access
page
But, as soon you’ve visited /directory/page-2
all other /directory/*
will get the insufficient-access
page served as well.
Expected Behavior
Do not rewrite all routes of a dynamic route, as soon as one of them is rewritten by middleware.
Link to reproduction
https://github.com/klaasman/nextjs-middleware-rewrite-bug
To Reproduce
- run a build
yarn build
(issue won’t happen in a development build) - start app
yarn start
- visit app localhost:3000
- click a “Page 1” link - target page is rendered
- hit back button
- click a “Page 2” link (of same section) - “no access” page is rendered
- hit back button
- click “Page 1” link - expected to see target page, instead we see the “no access” page. Refresh page to see target page.
Additionally there’s also this deployment: https://nextjs-middleware-rewrite-bug.vercel.app/ But for some reason the “get static props” example won’t work because the “page-1” route does a server round trip (= no client-side routing)… Possibly related with the root cause of the original issue, who knows.
The “get server-side props” example does show the issue.
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:7 (2 by maintainers)
Top GitHub Comments
Hi, this has been updated in
v12.2.4-canary.3
of Next.js, please update and give it a try!I was able to replicate the bug on my machine with your
getStaticProps
example, so maybe there’s a different Vercel-specific bug there?Based on this replay, here’s what seems to be happening: https://app.replay.io/recording/nextjs-middleware-rewrite-bugvercelapp--9e342552-070e-4f91-8ea2-6da032704536
/get-static-props/page-2
, Next.js detects client-side that this matches the dynamic route/get-static-props/[page]
, and passes this togetRouteInfo
. https://github.com/vercel/next.js/blob/81b554f3c1ffc93df992dcbc923079803f5ab1c5/packages/next/shared/lib/router/router.ts#L1243-L1246 https://github.com/vercel/next.js/blob/81b554f3c1ffc93df992dcbc923079803f5ab1c5/packages/next/shared/lib/router/router.ts#L1333-L1335getRouteInfo
checks the middleware response and discovers that/get-static-props/page-2
is rewritten to/insufficient-access
. https://github.com/vercel/next.js/blob/81b554f3c1ffc93df992dcbc923079803f5ab1c5/packages/next/shared/lib/router/router.ts#L1731-L1732This caching code was last modified in https://github.com/vercel/next.js/pull/37716, but it’s also possible that the PR just exposed a latent bug with the dynamic route resolution?