vercel/next.js
Server actions
Server actions are App-Router-only mutating endpoints declared with 'use server'. They can be invoked as form actions or as direct function calls from client components. The framework auto-encrypts arguments (when they cross the network), generates the action endpoint URLs, and routes posts back through the renderer.
Source: packages/next/src/server/app-render/action-handler.ts (51 KB).
End-to-end flow
sequenceDiagram
participant Browser
participant Client as Client component
participant Encrypt as encryption.ts
participant Server as action-handler.ts
participant Action as User action
Client->>Browser: await myAction(arg)
Browser->>Server: POST<br/>Next-Action: <id><br/>body: encoded args
Server->>Encrypt: decode + decrypt args
Encrypt-->>Server: arg list
Server->>Action: invoke
Action-->>Server: return value or rerender
Server->>Browser: Flight payload<br/>(action result + rerender)
Browser->>Client: resolve promiseCompilation
When the user writes 'use server' in a function, the SWC transform at crates/next-custom-transforms/ rewrites it:
- The function gets a stable, hashed action ID.
- The body is moved to a server-only module so client bundles don't contain it.
- The client side gets a stub that POSTs to the same page URL with
Next-Action: <id>header.
Server actions inventory is recorded in server-reference-manifest.json so the runtime can look up the action by ID.
Argument encryption
packages/next/src/server/app-render/encryption.ts (12 KB) handles the symmetric encryption of bound arguments. When a server action references closed-over variables that need to flow to the client and back, those values are AES-encrypted with a per-build key. This prevents tampering — a malicious client can't substitute different argument values in transit.
The key is derived from NEXT_SERVER_ACTIONS_ENCRYPTION_KEY (env var) or auto-generated and stored at build time. Encryption happens through encryption-utils.ts and encryption-utils-server.ts.
CSRF protection
packages/next/src/server/app-render/csrf-protection.ts (3 KB) enforces same-origin checks on action requests:
- The
Originheader must match the requestHost. - For action POSTs, the
Content-Typemust be one ofapplication/x-www-form-urlencoded,multipart/form-data, ortext/plain(form-compatible MIMEs that browsers send by default for cross-origin form posts).
validateRSCRequestHeaders was just enabled by default in commit 4ba05cc300 ("enable validateRSCRequestHeaders by default") — additional header validation that further locks down RSC endpoints.
Action handler
action-handler.ts is the server-side dispatcher. It:
- Reads the
Next-Actionheader from the request. - Looks up the action handler in
server-reference-manifest.json. - Reads and parses the request body (form data, JSON, or React's encoded format).
- Decrypts bound arguments via
encryption.ts. - Sets up the action async storage (
action-async-storage.external.ts). - Invokes the user's action.
- If the action returns a value, encodes it as a Flight payload.
- If the action calls
revalidatePath,revalidateTag, orredirect, those signal the renderer to produce a new page response.
The handler is large because it covers form-data parsing, file uploads (via busboy), and integration with all of redirect, revalidation, and after-tasks.
Form integration
next/form (packages/next/src/client/form.tsx) is a thin wrapper around <form> that recognizes server-action action props and adds:
- Optimistic navigation while the action runs.
- Progressive enhancement: works without JavaScript, then enhances after hydration.
The form-shared.tsx file handles the shared logic between server and client form components.
Logging
packages/next/src/server/dev/server-action-logger.ts adds verbose logs in dev: each action invocation is logged with its name, duration, and outcome.
Integration points
- Compiled by an SWC transform in
crates/next-custom-transforms/. - Recorded in
server-reference-manifest.jsonat build time. - Dispatched by
action-handler.tsvia the action async storage. - Encrypted args use a per-build key; CSRF check enforces same-origin.
Entry points for modification
- To change action dispatch:
packages/next/src/server/app-render/action-handler.ts. - To change CSRF rules:
packages/next/src/server/app-render/csrf-protection.ts. - To change argument encryption:
packages/next/src/server/app-render/encryption.ts. - To change form integration:
packages/next/src/client/form.tsxandform-shared.tsx.
Key source files
| File | Purpose |
|---|---|
packages/next/src/server/app-render/action-handler.ts |
Action dispatcher |
packages/next/src/server/app-render/encryption.ts |
Argument encryption |
packages/next/src/server/app-render/csrf-protection.ts |
Same-origin / CSRF enforcement |
packages/next/src/server/app-render/action-async-storage.external.ts |
Action context per invocation |
packages/next/src/client/form.tsx |
next/form component |
packages/next/src/client/components/use-action-queue.ts |
Client-side queueing of in-flight actions |
packages/next/src/client/components/unrecognized-action-error.ts |
Error for stale action IDs |
crates/next-custom-transforms/ |
SWC transform that rewrites 'use server' |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.