跳转到内容
This is an unmaintained snapshot of the Astro v4 docs. View the latest docs.

API 端点

Astro 允许你创建自定义端点来提供任何类型的数据。你可以使用它来生成图像、公开 RSS 文档或将它们用作 API 路由来为你的站点构建完整的 API。

在静态生成的站点中,你的自定义端点在构建时被调用以生成静态文件。如果你选择启用 SSR 模式,自定义端点会变成根据请求调用的实时服务器端点。静态和 SSR 端点的定义类似,但 SSR 端点支持附加额外的功能。

要想要创建自定义端点,请将 .js.ts 文件添加到 /pages 目录。.js.ts 这样的扩展名将在构建过程中被删除,因此文件名中应包含你要创建的数据的扩展名。例如,文件 src/pages/data.json.ts 将被构建为 API 端点 /data.json

端点导出一个 GET 函数(可选的以 async 导出),该函数接收具有类似于 Astro 全局属性的 上下文对象。在这里,它返回一个带有 nameurl 的 Response 对象,Astro 将在构建时调用它并使用 body 中的内容来生成文件。

// 输出: /builtwith.json
export async function GET({params, request}) {
return new Response(
JSON.stringify({
name: 'Astro',
url: 'https://astro.build/'
})
)
}

从 Astro v3.0 开始,返回的 Response 对象不再需要包含 encoding 属性。例如,生成一个二进制 png 图像:

src/pages/astro-logo.png.ts
export async function GET({ params, request }) {
const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
return new Response(await response.arrayBuffer());
}

你还可以使用 APIRoute 类型来约束 API 端点函数:

import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ params, request }) => {...}

端点支持与页面相同的 动态路由 功能。使用中括号包裹参数作为文件名,并导出 getStaticPaths() 函数。然后,你可以使用传递给 API 端点函数的 params 属性访问参数:

src/pages/api/[id].json.ts
import type { APIRoute } from 'astro';
const usernames = ["张三", "李四", "王五"]
export const GET: APIRoute = ({ params, request }) => {
const id = params.id;
return new Response(
JSON.stringify({
name: usernames[id]
})
)
};
export function getStaticPaths () {
return [
{ params: { id: "0"} },
{ params: { id: "1"} },
{ params: { id: "2"} },
]
}

这将在构建时生成三个 JSON 端点:/api/0.json/api/1.json/api/2.json。带端点的动态路由与页面的工作方式相同,但由于端点是一个函数而不是组件,因此 props 是不被支持的。

所有端点都会接收 request 属性,但在静态模式下,你只能访问 request.url。它将返回当前端点的完整 URL,其工作方式与 Astro.request.url 对页面的作用相同。

src/pages/request-path.json.ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
path: new URL(request.url).pathname
})
)
}

服务器端点(API 路由)

段落标题 服务器端点(API 路由)

静态文件的端点 部分中描述的所有内容均可以在 SSR 模式下使用:文件可以导出一个名为 GET 的函数,该函数接收具有类似于 Astro 全局属性的 上下文对象

但是,不同于 static 模式,当你使用路由的按需渲染模式时,端点将在请求时被构建。这解锁了在构建时不可用的新特性,并允许你构建 API 路由以监听请求,并在服务器上安全地执行代码。

默认情况下,路由将在 server 模式被按需渲染。而在 hybrid 模式下,必须使用 export const prerender = false 来避免每个自定义端点的预渲染。

相关操作指南: 调用服务器端点

服务器端点可以在不导出 getStaticPaths 的情况下访问 params。服务器端点可以返回一个 Response 对象,其允许你为返回的数据设置状态码和标头:

src/pages/[id].json.js
import { getProduct } from '../db';
export async function GET({ params }) {
const id = params.id;
const product = await getProduct(id);
if (!product) {
return new Response(null, {
status: 404,
statusText: 'Not found'
});
}
return new Response(
JSON.stringify(product), {
status: 200,
headers: {
"Content-Type": "application/json"
}
}
);
}

这将响应与动态路由匹配的任何请求。例如,如果我们导航到 /helmet.jsonparams.id 将被设置为 helmet。如果我们模拟的数据库中存在 helmet,端点将使用它创建一个包含 product 数据(格式化为 JSON)的 Response 对象,并返回成功的 HTTP状态码。如果没有,它将使用一个 Response 对象返回 404 响应。

在 SSR 模式下,需要提供 Content-Type 头来返回图像。在这种情况下,使用 Response 对象来指定 headers 属性。例如,生成一个二进制 .png 图像:

src/pages/astro-logo.png.ts
export async function GET({ params, request }) {
const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
const buffer = Buffer.from(await response.arrayBuffer());
return new Response(buffer, {
headers: { "Content-Type": "image/png" },
});
}

除了 GET 函数,你还可以使用任何 HTTP 方法 作为名称导出函数。当有请求进来时,Astro 会检查该方法并调用相应的函数。

你还可以导出 ALL 函数以匹配任何没有相应导出函数的方法。如果请求方法不匹配,它将重定向到你的网站的 404 页面

src/pages/methods.json.ts
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
message: "This was a GET!"
})
)
}
export const POST: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "This was a POST!"
})
)
}
export const DELETE: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "This was a DELETE!"
})
)
}
export const ALL: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: `This was a ${request.method}!`
})
)
}

在 SSR 模式下,request 属性返回一个可用的 Request 对象,该对象引用当前请求。这允许你接收数据并检查 headers

src/pages/test-post.json.ts
export const POST: APIRoute = async ({ request }) => {
if (request.headers.get("Content-Type") === "application/json") {
const body = await request.json();
const name = body.name;
return new Response(JSON.stringify({
message: "你的名字是:" + name
}), {
status: 200
})
}
return new Response(null, { status: 400 });
}

端点上下文导出一个类似于 Astro.redirectredirect() 函数:

src/pages/links/[id].js
import { getLinkUrl } from '../db';
export async function GET({ params }) {
const { id } = params;
const link = await getLinkUrl(id);
if (!link) {
return new Response(null, {
status: 404,
statusText: 'Not found'
});
}
return Response.redirect(link, 307);
}
贡献

你有什么想法?

社区