Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/next/src/server/app-render/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,17 @@ export async function handleAction({
}

// For an MPA action, the redirect doesn't need a body, just a Location header.
res.setHeader('Location', redirectUrl)
const appRelativeRedirectUrl = getAppRelativeRedirectUrl(
ctx.renderOpts.basePath,
host,
redirectUrl,
requestStore.url.pathname
)

res.setHeader(
'Location',
appRelativeRedirectUrl?.toString() ?? redirectUrl
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
appRelativeRedirectUrl?.toString() ?? redirectUrl
appRelativeRedirectUrl
? `${appRelativeRedirectUrl.pathname}${appRelativeRedirectUrl.search}${appRelativeRedirectUrl.hash}`
: redirectUrl

The Location header is being set to the full URL string including a dummy protocol/host (e.g., http://n/path) instead of just the pathname and search/hash. This will cause redirects to fail or behave unexpectedly.

View Details

Analysis

Location header includes invalid dummy host instead of just pathname

What fails: MPA (Multi-Page Application) action redirects set Location header to full URL with dummy host http://n/path instead of just /path

How to reproduce: In packages/next/src/server/app-render/action-handler.ts, when an MPA Server Action redirects with redirect('/'), the Location header is set using appRelativeRedirectUrl?.toString() which includes the dummy host used for URL parsing.

Result: Location header is set to http://n/path?query#hash instead of /path?query#hash. Browsers attempting to follow this redirect would try to connect to host "n" and fail.

Expected: According to RFC 7231, the Location header should contain either:

  • An absolute URI with real host: https://example.com/path
  • A URI-reference (pathname-only): /path

The code already demonstrates the correct pattern in lines 283 and 344, where it accesses pathname, search, and hash properties directly instead of calling .toString() on the URL object.

Fix: Changed line 1096 from appRelativeRedirectUrl?.toString() ?? redirectUrl to:

appRelativeRedirectUrl
  ? ` 

)
return {
type: 'done',
result: RenderResult.EMPTY,
Expand Down
Loading