Fix server action edge redirect with middleware rewrite (#67148)

### What

Add isEdgeRendering check condition for rewrite logic in edge adpator 

Fixes #66837 
Closes NEXT-3545

### Why

From headers `x-middleware-rewrite`, it's still relative url `/rewrite`,
reconstructing the url will lead to crash as it doesn't contain host.
This commit is contained in:
Jiachi Liu 2024-06-24 15:17:44 +02:00 committed by GitHub
parent 6604c187ec
commit 7f72971039
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 97 additions and 1 deletions

View file

@ -300,7 +300,7 @@ export async function adapter(
* a data URL if the request was a data request.
*/
const rewrite = response?.headers.get('x-middleware-rewrite')
if (response && rewrite) {
if (response && rewrite && !isEdgeRendering) {
const rewriteUrl = new NextURL(rewrite, {
forceLocale: true,
headers: params.request.headers,

View file

@ -0,0 +1,11 @@
'use server'
import { redirect } from 'next/navigation'
export async function relativeRedirect() {
return redirect('./subpage')
}
export async function absoluteRedirect() {
return redirect('/subpage')
}

View file

@ -0,0 +1,11 @@
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html>
<body>{children}</body>
</html>
)
}

View file

@ -0,0 +1,3 @@
export default function Page() {
return <div id="redirected">Redirected</div>
}

View file

@ -0,0 +1,7 @@
'use server'
import { redirect } from 'next/navigation'
export const redirectAction = async () => {
redirect('/redirect')
}

View file

@ -0,0 +1,13 @@
'use client'
import { redirectAction } from '../_action'
export default function Page() {
return (
<form action={redirectAction}>
<button type="submit">Submit</button>
</form>
)
}
export const runtime = 'edge'

View file

@ -0,0 +1,13 @@
'use client'
import { redirectAction } from '../_action'
export default function Page() {
return (
<form action={redirectAction}>
<button type="submit">Submit</button>
</form>
)
}
export const runtime = 'nodejs'

View file

@ -0,0 +1,5 @@
import { NextRequest, NextResponse } from 'next/server'
export default function middleware(request: NextRequest) {
return NextResponse.rewrite(request.url)
}

View file

@ -0,0 +1,33 @@
import { nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils'
describe('app-dir - server-actions-redirect-middleware-rewrite.test', () => {
const { next } = nextTestSetup({
files: __dirname,
})
it('should redirect correctly in nodejs runtime with middleware rewrite', async () => {
const browser = await next.browser('/server-action/node')
await browser.waitForElementByCss('button').click()
await retry(async () => {
expect(await browser.waitForElementByCss('#redirected').text()).toBe(
'Redirected'
)
})
expect(await browser.url()).toBe(`${next.url}/redirect`)
})
it('should redirect correctly in edge runtime with middleware rewrite', async () => {
const browser = await next.browser('/server-action/edge')
await browser.waitForElementByCss('button').click()
await retry(async () => {
expect(await browser.waitForElementByCss('#redirected').text()).toBe(
'Redirected'
)
expect(await browser.url()).toBe(`${next.url}/redirect`)
})
})
})