17. API-маршруты (Endpoints)
Astro позволяет создавать серверные API-эндпоинты прямо в папке src/pages/api/. Это полноценные HTTP-обработчики — GET, POST, PUT, DELETE — без отдельного бэкенд-сервера.
Думай об API-маршрутах Astro как о serverless-функциях, встроенных прямо в твой проект: создал файл — получил эндпоинт.
Структура API-файла
Заголовок раздела «Структура API-файла»import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ request, url, cookies }) => { const posts = await fetchPosts(); return new Response(JSON.stringify(posts), { status: 200, headers: { 'Content-Type': 'application/json' }, });};
export const POST: APIRoute = async ({ request }) => { const body = await request.json(); const newPost = await createPost(body); return new Response(JSON.stringify(newPost), { status: 201 });};Объекты Request и Response
Заголовок раздела «Объекты Request и Response»Astro использует стандартные Web API:
// Requestconst url = new URL(request.url);const params = url.searchParams; // GET-параметрыconst body = await request.json(); // JSON-телоconst formData = await request.formData(); // Form dataconst headers = request.headers; // Заголовки
// Responsereturn new Response(JSON.stringify(data), { status: 200, headers: { 'Content-Type': 'application/json', 'Cache-Control': 'max-age=3600', 'X-Custom-Header': 'value', },});Динамические API-маршруты
Заголовок раздела «Динамические API-маршруты»export const GET: APIRoute = async ({ params }) => { const { id } = params; const post = await getPost(id);
if (!post) { return new Response(JSON.stringify({ error: 'Not found' }), { status: 404, }); }
return new Response(JSON.stringify(post));};
export const DELETE: APIRoute = async ({ params }) => { await deletePost(params.id); return new Response(null, { status: 204 });};Обработка форм
Заголовок раздела «Обработка форм»<form method="POST" action="/api/contact"> <input name="email" type="email" /> <textarea name="message"></textarea> <button type="submit">Отправить</button></form>export const POST: APIRoute = async ({ request, redirect }) => { const data = await request.formData(); const email = data.get('email'); const message = data.get('message');
await sendEmail({ email, message }); return redirect('/thanks', 302);};Middleware для API
Заголовок раздела «Middleware для API»export const onRequest = async (context, next) => { // Проверка API-ключа для /api/* маршрутов if (context.url.pathname.startsWith('/api/')) { const apiKey = context.request.headers.get('X-API-Key'); if (apiKey !== import.meta.env.SECRET_API_KEY) { return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401, }); } } return next();};Утилиты для удобных ответов
Заголовок раздела «Утилиты для удобных ответов»// Хелпер для JSON-ответовfunction json(data: unknown, status = 200) { return new Response(JSON.stringify(data), { status, headers: { 'Content-Type': 'application/json' }, });}
// Использованиеexport const GET: APIRoute = () => json({ ok: true });export const POST: APIRoute = async ({ request }) => { const body = await request.json(); return json({ created: true, id: 42 }, 201);};