diff --git a/packages/next/shared/lib/router/router.ts b/packages/next/shared/lib/router/router.ts index d828f29d9774359..9a41567ba0bface 100644 --- a/packages/next/shared/lib/router/router.ts +++ b/packages/next/shared/lib/router/router.ts @@ -1853,7 +1853,15 @@ export default class Router implements BaseRouter { shouldCache: options.cache, }) - if (preflight.rewrite?.startsWith('/')) { + if (preflight.rewrite) { + // for external rewrites we need to do a hard navigation + // to the resource + if (!preflight.rewrite.startsWith('/')) { + return { + type: 'redirect', + destination: options.as, + } + } const parsed = parseRelativeUrl( normalizeLocalePath( hasBasePath(preflight.rewrite) diff --git a/test/integration/middleware/core/pages/rewrites/_middleware.js b/test/integration/middleware/core/pages/rewrites/_middleware.js index bc8bd0153e386b7..9365a1ca1713aa5 100644 --- a/test/integration/middleware/core/pages/rewrites/_middleware.js +++ b/test/integration/middleware/core/pages/rewrites/_middleware.js @@ -6,6 +6,16 @@ import { NextResponse } from 'next/server' export async function middleware(request) { const url = request.nextUrl + if ( + url.pathname.startsWith('/rewrites/about') && + url.searchParams.has('override') + ) { + const isExternal = url.searchParams.get('override') === 'external' + return NextResponse.rewrite( + isExternal ? 'https://example.com' : '/rewrites/a' + ) + } + if (url.pathname.startsWith('/rewrites/to-blog')) { const slug = url.pathname.split('/').pop() url.pathname = `/rewrites/fallback-true-blog/${slug}` diff --git a/test/integration/middleware/core/pages/rewrites/index.js b/test/integration/middleware/core/pages/rewrites/index.js index 0f347114ed0ed09..f15b3557ed56234 100644 --- a/test/integration/middleware/core/pages/rewrites/index.js +++ b/test/integration/middleware/core/pages/rewrites/index.js @@ -24,6 +24,14 @@ export default function Home() { Rewrite me without a hard navigation +
+ + Rewrite me to external site + +
+ + Rewrite me to internal path +
) } diff --git a/test/integration/middleware/core/test/index.test.js b/test/integration/middleware/core/test/index.test.js index 5a5959374e01791..1344e13a6fd3339 100644 --- a/test/integration/middleware/core/test/index.test.js +++ b/test/integration/middleware/core/test/index.test.js @@ -162,6 +162,56 @@ function urlTests(log, locale = '') { } function rewriteTests(log, locale = '') { + it('should override with rewrite internally correctly', async () => { + const res = await fetchViaHTTP( + context.appPort, + '/rewrites/about', + { override: 'internal' }, + { redirect: 'manual' } + ) + + expect(res.status).toBe(200) + expect(await res.text()).toContain('Welcome Page A') + + const browser = await webdriver(context.appPort, `${locale}/rewrites`) + await browser.elementByCss('#override-with-internal-rewrite').click() + await check( + () => browser.eval('document.documentElement.innerHTML'), + /Welcome Page A/ + ) + expect(await browser.eval('window.location.pathname')).toBe( + `${locale || ''}/rewrites/about` + ) + expect(await browser.eval('window.location.search')).toBe( + '?override=internal' + ) + }) + + it('should override with rewrite externally correctly', async () => { + const res = await fetchViaHTTP( + context.appPort, + '/rewrites/about', + { override: 'external' }, + { redirect: 'manual' } + ) + + expect(res.status).toBe(200) + expect(await res.text()).toContain('Example Domain') + + const browser = await webdriver(context.appPort, `${locale}/rewrites`) + await browser.elementByCss('#override-with-external-rewrite').click() + await check( + () => browser.eval('document.documentElement.innerHTML'), + /Example Domain/ + ) + expect(await browser.eval('window.location.pathname')).toBe( + `${locale || ''}/rewrites/about` + ) + expect(await browser.eval('window.location.search')).toBe( + '?override=external' + ) + }) + it('should rewrite to fallback: true page successfully', async () => { const randomSlug = `another-${Date.now()}` const res2 = await fetchViaHTTP(