Перейти к содержимому

Эндпойнты

Astro позволяет создавать пользовательские эндпойнты для работы с любыми типами данных. Вы можете использовать их для генерации изображений, предоставления RSS-документов или в качестве API-маршрутов для построения полноценного API вашего сайта.

На статически генерируемых сайтах пользовательские эндпойнты вызываются во время сборки для создания статических файлов. При включении режима SSR эндпойнты работают на сервере и обрабатывают запросы в реальном времени. Хотя статические и SSR-эндпойнты определяются одинаково, SSR-эндпойнты предоставляют больше возможностей.

Чтобы создать пользовательский эндпойнт, добавьте файл .js или .ts в директорию /pages. Расширение .js или .ts будет удалено в процессе сборки, поэтому включите в имя файла расширение данных, которые вы хотите создать. Например, файл src/pages/data.json.ts сгенерирует эндпойнт /data.json.

Эндпойнты экспортируют функцию GET (которая может быть асинхронной), принимающую объект контекста со свойствами, аналогичными глобальному объекту Astro. Функция возвращает объект Response с полями name и url. Astro вызовет эту функцию во время сборки и использует тело ответа для генерации файла.

src/pages/builtwith.json.ts
// Результат: /builtwith.json
export 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:

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

Эндпойнты поддерживают те же возможности динамической маршрутизации, что и страницы. Назовите файл, используя параметр в квадратных скобках, и экспортируйте функцию getStaticPaths() (EN). После этого вы получите доступ к параметру через свойство 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" } },
{ params: { id: "3" } },
];
}

Это сгенерирует четыре JSON-эндпойнта во время сборки: /api/0.json, /api/1.json, /api/2.json и /api/3.json. Динамическая маршрутизация эндпойнтов работает так же, как и для страниц, но поскольку эндпойнт — это функция, а не компонент, props (EN) не поддерживаются.

Все эндпойнты имеют свойство 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,
}),
);
};

Все описанные возможности статических эндпойнтов также работают в режиме SSR: вы можете экспортировать функцию GET, которая принимает объект контекста со свойствами, аналогичными глобальному объекту Astro.

Однако, в отличие от статического режима, при включении рендеринга по запросу эндпойнт генерируется в момент обращения к нему. Это открывает доступ к новым возможностям, недоступным при статической сборке, и позволяет создавать API-маршруты, которые обрабатывают запросы и безопасно выполняют код на сервере в реальном времени.

В режиме server маршруты по умолчанию обрабатываются по запросу. В режиме static для каждого пользовательского эндпойнта нужно явно отключить предварительный рендеринг, указав export const prerender = false.

Связанная инструкция: Вызов эндпоинтов с сервера

Серверные эндпойнты могут обращаться к params без экспорта getStaticPaths и возвращать объект 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: "Не найдено",
});
}
return new Response(JSON.stringify(product), {
status: 200,
headers: {
"Content-Type": "application/json",
},
});
}

Этот эндпойнт обрабатывает любой запрос, соответствующий динамическому маршруту. Например, при обращении к /helmet.json параметр params.id будет равен helmet. Если helmet существует в тестовой базе данных продуктов, эндпойнт вернёт JSON-ответ с успешным HTTP статус-кодом. В противном случае будет возвращён ответ с кодом 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: "Это был GET-запрос!",
}),
);
};
export const POST: APIRoute = ({ request }) => {
return new Response(
JSON.stringify({
message: "Это был POST-запрос!",
}),
);
};
export const DELETE: APIRoute = ({ request }) => {
return new Response(
JSON.stringify({
message: "Это был DELETE-запрос!",
}),
);
};
export const ALL: APIRoute = ({ request }) => {
return new Response(
JSON.stringify({
message: `Это был ${request.method}!`,
}),
);
};

При наличии функции GET и отсутствии функции HEAD Astro автоматически обрабатывает HEAD-запросы, вызывая функцию GET и отделяя тело ответа от заголовков.

В режиме SSR свойство request предоставляет полнофункциональный объект Request для работы с текущим запросом. С его помощью можно получать данные и проверять заголовки:

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 });
};

В контексте эндпойнта доступна утилита redirect(), работающая аналогично Astro.redirect:

src/pages/links/[id].js
import { getLinkUrl } from "../db";
export async function GET({ params, redirect }) {
const { id } = params;
const link = await getLinkUrl(id);
if (!link) {
return new Response(null, {
status: 404,
statusText: "Не найдено",
});
}
return redirect(link, 307);
}
Внести свой вклад Сообщество Sponsor