Actions API 参考
新增于: astro@4.15.0
Actions 帮助你构建一个可以从客户端代码和 HTML 表单调用的类型安全的后端。所有用于定义和调用 Action 的实用工具都由 astro:actions
模块暴露。有关示例和使用说明,请参阅 Actions 指南。
从 astro:actions
导入
标题为“从 astro:actions 导入”的部分import { actions, defineAction, isInputError, isActionError, ActionError, } from 'astro:actions';
defineAction()
标题为“defineAction()”的部分
新增于: astro@4.15.0
defineAction()
工具用于在 src/actions/index.ts
文件中定义新的 Action。它接受一个包含要运行的服务器逻辑的 handler()
函数,以及一个可选的用于在运行时验证输入参数的 input
属性。
import { defineAction } from 'astro:actions';import { z } from 'astro:schema';
export const server = { getGreeting: defineAction({ input: z.object({ name: z.string(), }), handler: async (input, context) => { return `Hello, ${input.name}!` } })}
handler()
属性
标题为“handler() 属性”的部分类型: (input, context) => any
defineAction()
需要一个 handler()
函数,其中包含在调用 Action 时要运行的服务器逻辑。从处理程序返回的数据会自动序列化并发送给调用者。
handler()
的第一个参数是用户输入。如果设置了 input
验证器,用户输入将在传递给处理程序之前被验证。第二个参数是一个 context
对象,包含 Astro 的大部分标准端点上下文,但不包括 getActionResult()
、callAction()
和 redirect()
。
返回值使用 devalue 库进行解析。它支持 JSON 值以及 Date()
、Map()
、Set()
和 URL()
的实例。
input
验证器
标题为“input 验证器”的部分类型: ZodType | undefined
可选的 input
属性接受一个 Zod 验证器(例如 Zod 对象、Zod 可辨识联合类型)以在运行时验证处理程序的输入。如果 Action 验证失败,将返回一个BAD_REQUEST
错误,并且不会调用 handler
。
如果省略 input
,对于 JSON 请求,handler
将接收类型为 unknown
的输入;对于表单请求,将接收类型为 FormData
的输入。
与 accept: 'form'
一起使用
标题为“与 `accept: 'form'` 一起使用”的部分如果你的 Action 接受表单输入,请使用 z.object()
验证器将表单数据自动解析为类型化对象。所有 Zod 验证器都支持表单数据字段(例如 z.coerce.date()
)。为方便起见,Astro 还在底层为验证以下类型的字段输入提供了特殊处理:
number
类型的输入可以使用z.number()
进行验证checkbox
类型的输入可以使用z.coerce.boolean()
进行验证file
类型的输入可以使用z.instanceof(File)
进行验证- 具有相同
name
的多个输入可以使用z.array(/* 验证器 */)
进行验证 - 所有其他输入都可以使用
z.string()
进行验证
扩展函数,包括 .refine()
、.transform()
和 .pipe()
,在 z.object()
验证器上也受支持。
要应用不同验证器的联合,请使用 z.discriminatedUnion()
包装器,根据特定的表单字段来缩小类型范围。此示例接受一个用于“创建”或“更新”用户的表单提交,并使用名为 type
的表单字段来确定要针对哪个对象进行验证。
import { defineAction } from 'astro:actions';import { z } from 'astro:schema';
export const server = { changeUser: defineAction({ accept: 'form', input: z.discriminatedUnion('type', [ z.object({ // Matches when the `type` field has the value `create` type: z.literal('create'), name: z.string(), email: z.string().email(), }), z.object({ // Matches when the `type` field has the value `update` type: z.literal('update'), id: z.number(), name: z.string(), email: z.string().email(), }), ]), async handler(input) { if (input.type === 'create') { // input is { type: 'create', name: string, email: string } } else { // input is { type: 'update', id: number, name: string, email: string } } }, }),};
isInputError()
标题为“isInputError()”的部分类型: (error?: unknown | ActionError) => boolean
astro@4.15.0
isInputError()
工具用于检查一个 ActionError
是否是输入验证错误。当 input
验证器是 z.object()
时,输入错误会包含一个 fields
对象,其中按名称分组了错误消息。
isInputError()
的更多信息,请参阅表单输入错误指南。
isActionError()
标题为“isActionError()”的部分类型: (error?: unknown | ActionError) => boolean
astro@4.15.0
isActionError()
工具用于检查你的 Action 是否在处理程序属性中抛出了一个 ActionError
。这在 try / catch
块中缩小通用错误类型时非常有用。
ActionError
标题为“ActionError”的部分
新增于: astro@4.15.0
ActionError()
构造函数用于创建由 Action handler
抛出的错误。它接受一个描述所发生错误的 code
属性(例如:"UNAUTHORIZED"
),以及一个可选的包含更多详细信息的 message
属性。
错误码
标题为“code”的部分
新增于: astro@4.15.0
code
属性接受所有 HTTP 状态码的人类可读版本。支持以下代码:
BAD_REQUEST
(400):客户端发送了无效的输入。当 Actioninput
验证器验证失败时,会抛出此错误。UNAUTHORIZED
(401):客户端缺少有效的身份验证凭据。FORBIDDEN
(403):客户端未被授权访问资源。NOT_FOUND
(404):服务器找不到请求的资源。METHOD_NOT_SUPPORTED
(405):服务器不支持请求的方法。TIMEOUT
(408):服务器在处理请求时超时。CONFLICT
(409):由于冲突,服务器无法更新资源。PRECONDITION_FAILED
(412):服务器不满足请求的先决条件。PAYLOAD_TOO_LARGE
(413):由于有效负载过大,服务器无法处理请求。UNSUPPORTED_MEDIA_TYPE
(415):服务器不支持请求的媒体类型。注意:Actions 已经为 JSON 和表单请求检查Content-Type
标头,因此你可能不需要手动引发此代码。UNPROCESSABLE_CONTENT
(422):由于语义错误,服务器无法处理请求。TOO_MANY_REQUESTS
(429):服务器已超过指定的速率限制。CLIENT_CLOSED_REQUEST
(499):客户端在服务器响应前关闭了请求。INTERNAL_SERVER_ERROR
(500):服务器意外失败。NOT_IMPLEMENTED
(501):服务器不支持请求的功能。BAD_GATEWAY
(502):服务器从上游服务器收到了无效的响应。SERVICE_UNAVAILABLE
(503):服务器暂时不可用。GATEWAY_TIMEOUT
(504):服务器从上游服务器收到超时。
新增于: astro@4.15.0
message
属性接受一个字符串。(例如“用户必须登录。”)
getActionContext()
标题为“getActionContext()”的部分类型: (context: APIContext) => ActionMiddlewareContext
astro@5.0.0
getActionContext()
是一个从你的中间件处理程序中调用的函数,用于检索有关入站 Action 请求的信息。
此函数返回一个包含请求信息的 action
对象,以及用于以编程方式设置 Astro.getActionResult()
返回值的 setActionResult()
和 serializeActionResult()
函数。
getActionContext()
允许你使用中间件以编程方式获取和设置 Action 结果,从而可以持久化来自 HTML 表单的 Action 结果,通过增加的安全检查来控制 Action 请求等。
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action?.calledFrom === 'form') { const result = await action.handler(); setActionResult(action.name, serializeActionResult(result)); } return next();});
类型: { calledFrom: 'rpc' | 'form', name: string, handler: () => Promise<SafeResult<any, any>> } | undefined
action
是一个包含有关入站 Action 请求信息的对象。
它可以从 getActionContext()
中获得,并提供 Action 名称、处理程序,以及该 Action 是从客户端 RPC 函数(例如 actions.newsletter()
)调用还是从 HTML 表单操作调用。
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action?.calledFrom === 'rpc' && action.name.startsWith('private')) { // Check for a valid session token } // ...});
setActionResult()
标题为“setActionResult()”的部分类型: (actionName: string, actionResult: SerializedActionResult) => void
setActionResult()
是一个用于在中间件中以编程方式设置 Astro.getActionResult()
返回值的函数。它接收 Action 名称和由 serializeActionResult()
序列化的 Action 结果。
当从 HTML 表单调用 Action 以持久化和从会话加载结果时,这非常有用。
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action?.calledFrom === 'form') { const result = await action.handler(); // ... handle the action result setActionResult(action.name, serializeActionResult(result)); } return next();});
serializeActionResult()
标题为“serializeActionResult()”的部分类型: (result: SafeResult<any, any>) => SerializedActionResult
serializeActionResult()
会将 Action 结果序列化为 JSON 以便持久化。这是正确处理非 JSON 返回值(如 Map
或 Date
)以及 ActionError
对象所必需的。
在序列化要传递给 setActionResult()
的 Action 结果时调用此函数。
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action) { const result = await action.handler(); setActionResult(action.name, serializeActionResult(result)); } // ...});
deserializeActionResult()
标题为“deserializeActionResult()”的部分类型: (result: SerializedActionResult) => SafeResult<any, any>
deserializeActionResult()
将反转 serializeActionResult()
的效果,并将 Action 结果恢复到其原始状态。这对于访问序列化 Action 结果上的 data
和 error
对象非常有用。
getActionPath()
标题为“getActionPath()”的部分类型: (action: ActionClient<any, any, any>) => string
astro@5.1.0
getActionPath()
工具接受一个 Action 并返回一个 URL 路径,以便你可以直接将 Action 调用作为 fetch()
操作执行。这允许你在调用 Action 时提供自定义标头等详细信息。然后,你可以根据需要处理自定义格式的返回数据,就像直接调用 Action 一样。
此示例展示了如何调用一个已定义的 like
Action,并传递 Authorization
标头和 keepalive
选项。
<script>import { actions, getActionPath } from 'astro:actions'
await fetch(getActionPath(actions.like), { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer YOUR_TOKEN' }, body: JSON.stringify({ id: 'YOUR_ID' }), keepalive: true})</script>
此示例展示了如何使用 sendBeacon
API 调用相同的 like
Action。
<script>import { actions, getActionPath } from 'astro:actions'
navigator.sendBeacon( getActionPath(actions.like), new Blob([JSON.stringify({ id: 'YOUR_ID' })], { type: 'application/json' }))</script>