Skip to content

Commit

Permalink
Ensure external middleware rewrite is handled correctly (vercel#33962)
Browse files Browse the repository at this point in the history
  • Loading branch information
ijjk authored and natew committed Feb 16, 2022
1 parent 7a6f5a3 commit 7e8b5da
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 1 deletion.
10 changes: 9 additions & 1 deletion packages/next/shared/lib/router/router.ts
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions test/integration/middleware/core/pages/rewrites/_middleware.js
Expand Up @@ -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}`
Expand Down
8 changes: 8 additions & 0 deletions test/integration/middleware/core/pages/rewrites/index.js
Expand Up @@ -24,6 +24,14 @@ export default function Home() {
<Link href="/rewrites/rewrite-me-without-hard-navigation?message=refreshed">
<a id="link-with-rewritten-url">Rewrite me without a hard navigation</a>
</Link>
<div />
<Link href="/rewrites/about?override=external">
<a id="override-with-external-rewrite">Rewrite me to external site</a>
</Link>
<div />
<Link href="/rewrites/about?override=internal">
<a id="override-with-internal-rewrite">Rewrite me to internal path</a>
</Link>
</div>
)
}
50 changes: 50 additions & 0 deletions test/integration/middleware/core/test/index.test.js
Expand Up @@ -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(
Expand Down

0 comments on commit 7e8b5da

Please sign in to comment.