Files
Janka UrygaandGitHub 7fc1a200cc fix: request APIs in promises passed to after() in actions/handlers (#94964)
Fixes a bug where Route Handlers and Server Actions were prevented from
calling `headers()` (and other request APIs) if
- the call happened after the response is finished
- the call *did not happen* inside an after-callback
generally, this happens when you pass a promise to after.
```ts
const longRunning = () => {
  // assume this resolves after the response
  await new Promise((resolve) => setTimeout(resolve, 100))
  // response is done
  after(() => {
    await headers() // ❌ should be allowed, but throws
  })
}

after(longRunning()) // or waitUntil, doesn't matter
```

The logic we used in the check was incorrect and assumed that an
`afterTaskStore` was present, but we can only wrap callbacks in this ALS
- we cannot change the async context of already-running promises.

One noteworthy change is that i had to exit `actionAsyncStorage` when we
do a render after the server action. Otherwise the checks in
`isRequestApiAllowedInCurrentPhase` might believe that they're still in
a server action when they aren't.
2026-06-19 19:23:06 +00:00

19 lines
472 B
TypeScript

import { testApiInPromisePassedToAfter, REQUEST_API_NAMES } from '../common'
async function action(apiName: string) {
'use server'
testApiInPromisePassedToAfter('action', apiName)
}
export default async function Page() {
return (
<main>
{REQUEST_API_NAMES.map((apiName) => (
<form data-api-name={apiName} action={action.bind(null, apiName)}>
<button type="submit">Submit - {apiName}</button>
</form>
))}
</main>
)
}