API 路由
src/pages 中没有同名页面模块的 *.server.ts 是 API 路由,按 HTTP 方法导出处理函数。
// src/pages/api/likes/[slug].server.ts -> /api/likes/:slug
import type { ServerLoadContext } from '@mantou/gemkit';
type Context = ServerLoadContext<{ slug: string }>;
// 返回 `Response` 以外的值会作为 JSON 响应。
export const GET = ({ params }: Context) => ({ likes: getLikes(params.slug) });
// 第二个参数是输入:`GET` 和 `DELETE` 是查询参数,其他方法是 JSON 请求体。
export const POST = ({ params }: Context, input: { count: number }) => ({
likes: addLikes(params.slug, input.count),
});
export const DELETE = () => new Response(null, { status: 204 });文件映射
| 文件 | URL |
|---|---|
src/pages/api/likes/[slug].server.ts |
/api/likes/:slug |
src/pages/api/likes/index.server.ts |
/api/likes |
src/pages/rss.xml.server.ts |
/rss.xml |
API 路由没有语言前缀。handle 在处理函数之前执行,event.path 是 API 路径。
参数和 load 相同:params、url、request、cookies 和 locals。
处理函数中设置的 cookie 会添加到响应中。
支持的方法有 GET、POST、PUT、PATCH 和 DELETE。只导出 GET 时,HEAD 使用 GET。
其他方法响应 405,并带有 Allow 头。
响应
- 返回
Response可以控制状态码、响应头和内容。 - 返回其他值会作为 JSON 响应。
redirect(status, location)响应跳转。error(status, message)响应{ status, message }的 JSON。
抛出的意外错误响应状态码 500 和 JSON 错误,在服务端会交给 src/app.server.ts 的 handleError。
类型化客户端
$gemkit/api 根据 API 路由生成。静态路径段是属性,动态段是函数调用,最后是 HTTP 方法,
参数和结果都从处理函数推导:
const result = await apis.api.likes(slug).POST({ count: 1 });
const res = await apis.api.likes(slug).DELETE();
// 属性可以解构,调用链从第一个动态段开始。
const { api } = apis;
const likes = await api.likes(slug).GET();- 请求发送到 API 路径,不包含语言前缀。
- JSON 响应会解析,其他响应返回原始
Response。 error()响应会 rejectHttpError,它有status和message。- 输入只有类型,需要校验内容时在处理函数中检查,例如写入数据库之前。
- 处理函数仍然可以自己读取
request,例如request.formData()。
安全
- 跨站的表单类型请求(
application/x-www-form-urlencoded、multipart/form-data、text/plain) 会被拒绝(CSRF)。 - 其他跨站请求需要 CORS 预检。没有
Origin的请求(例如 webhook)不受影响。 - 一组 API 路由的权限检查使用
。handle
部署
API 路由不会被预渲染。开发时和 gemkit start 可以使用,静态托管不可用。
