Files
Zack TannerandGitHub ccfe67aa8d Return 200 for client-handled Server Action redirects (#96310)
## Summary

Client-handled Server Action redirects currently return a `303` without
a `Location` header and may include a streamed RSC response body. Some
HTTP intermediaries reject this response or strip its body because it
looks like an HTTP redirect.

Return `200` for client-handled Server Action redirects while continuing
to use `x-action-redirect` and the RSC response. Progressive-enhancement
form submissions still return a standards-compliant `303` with
`Location`.

Fixes #92882
Fixes #74026

## Verification

- `HEADLESS=true pnpm test-dev-turbo
test/e2e/app-dir/actions/app-action.test.ts
test/e2e/app-dir/app-basepath/index.test.ts
test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts`
- `HEADLESS=true pnpm test-start-turbo
test/e2e/app-dir/actions/app-action.test.ts
test/e2e/app-dir/app-basepath/index.test.ts
test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts`
- `pnpm --filter=next types`

<!-- NEXT_JS_LLM -->
2026-07-28 16:04:34 -04:00

51 lines
1.1 KiB
JavaScript

'use server'
import { redirect } from 'next/navigation'
import { notFound } from 'next/navigation'
// Simple successful action
export async function successAction(value) {
return { result: value + 1 }
}
// Action with multiple arguments
export async function multiArgAction(a, b, c) {
return { sum: a + b + c }
}
// Action that redirects
export async function redirectAction(path) {
redirect(path)
}
// Action that throws notFound (should show 404 status)
export async function notFoundAction() {
notFound()
}
// Action that throws an error (should show 500 status)
export async function errorAction() {
throw new Error('Intentional error for testing')
}
// Action with object argument
export async function objectArgAction(data) {
return { received: data }
}
// Action with array argument
export async function arrayArgAction(items) {
return { count: items.length }
}
// Inline action export for testing inline action display
export const inlineAction = async (value) => {
return value * 2
}
// Action with promise argument
export async function promiseArgAction(promiseValue) {
const resolved = await promiseValue
return { resolved }
}