diff --git a/packages/next/src/shared/lib/router/router.ts b/packages/next/src/shared/lib/router/router.ts index 088c34aa1d7a..a164d6c63d5f 100644 --- a/packages/next/src/shared/lib/router/router.ts +++ b/packages/next/src/shared/lib/router/router.ts @@ -227,9 +227,14 @@ function getMiddlewareData( const parsedSource = getNextPathnameInfo( parseRelativeUrl(source).pathname, { - nextConfig: process.env.__NEXT_HAS_REWRITES - ? undefined - : nextConfig, + // Pass basePath (and trailingSlash) so the basePath prefix is + // stripped before the `_next/data/` check, but omit `i18n` so the + // locale prefix is preserved here — the rewrite resolver below + // handles the locale-prefixed `as`. + nextConfig: { + basePath: nextConfig.basePath, + trailingSlash: nextConfig.trailingSlash, + }, parseData: true, } ) diff --git a/test/e2e/middleware-dynamic-basepath-matcher-rewrites/middleware-dynamic-basepath-matcher-rewrites.test.ts b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/middleware-dynamic-basepath-matcher-rewrites.test.ts new file mode 100644 index 000000000000..93b0863623ea --- /dev/null +++ b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/middleware-dynamic-basepath-matcher-rewrites.test.ts @@ -0,0 +1,19 @@ +import { nextTestSetup } from 'e2e-utils' +import { retry } from 'next-test-utils' + +describe('middleware-dynamic-basepath-matcher-rewrites', () => { + const { next } = nextTestSetup({ + files: __dirname, + }) + + it('preserves router.query on client-side navigation to a catch-all page', async () => { + const browser = await next.browser('/docs') + await browser.elementById('catchall-link').click() + + await retry(async () => { + expect(await browser.elementById('page-title').text()).toBe('CatchAll') + }) + + expect(await browser.elementById('query-path').text()).toBe('["first"]') + }) +}) diff --git a/test/e2e/middleware-dynamic-basepath-matcher-rewrites/middleware.js b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/middleware.js new file mode 100644 index 000000000000..9702fc711463 --- /dev/null +++ b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/middleware.js @@ -0,0 +1,9 @@ +import { NextResponse } from 'next/server' + +export default function middleware() { + return NextResponse.next() +} + +export const config = { + matcher: '/:path*', +} diff --git a/test/e2e/middleware-dynamic-basepath-matcher-rewrites/next.config.js b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/next.config.js new file mode 100644 index 000000000000..74a5f22a11d9 --- /dev/null +++ b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/next.config.js @@ -0,0 +1,8 @@ +module.exports = { + basePath: '/docs', + async rewrites() { + // Any non-empty rewrites array sets __NEXT_HAS_REWRITES=true; this entry + // only exists to flip that build flag, it isn't expected to match. + return [{ source: '/never-matched-rewrite', destination: '/never' }] + }, +} diff --git a/test/e2e/middleware-dynamic-basepath-matcher-rewrites/pages/[...path].tsx b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/pages/[...path].tsx new file mode 100644 index 000000000000..3d25ccc901ff --- /dev/null +++ b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/pages/[...path].tsx @@ -0,0 +1,15 @@ +import { useRouter } from 'next/router' + +export default function CatchAll() { + const router = useRouter() + return ( +
+

CatchAll

+

{JSON.stringify(router.query.path)}

+
+ ) +} + +export async function getServerSideProps() { + return { props: {} } +} diff --git a/test/e2e/middleware-dynamic-basepath-matcher-rewrites/pages/index.tsx b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/pages/index.tsx new file mode 100644 index 000000000000..de044e9c8068 --- /dev/null +++ b/test/e2e/middleware-dynamic-basepath-matcher-rewrites/pages/index.tsx @@ -0,0 +1,9 @@ +import Link from 'next/link' + +export default function Home() { + return ( + + Go to catchall + + ) +}