Обработчики маршрутов: свой API
Обработчик маршрута (route handler) — файл route.ts, который отвечает на HTTP-запросы данными, а не страницей. Так в Next.js делают API: для мобильного приложения, для чужих сайтов или для запросов из клиентских компонентов. Для форм на своём сайте обычно хватает серверных действий.
Первый обработчик
Создайте файл app/api/hello/route.ts:
// app/api/hello/route.ts
export async function GET() {
return Response.json({ message: 'Привет из API' });
}Имя экспортированной функции — HTTP-метод. Откройте http://localhost:3000/api/hello — браузер покажет {"message":"Привет из API"}. Объект Response — стандартный веб-API; метод Response.json превращает объект в JSON.
Данные комментариев
Комментарии будем хранить так же, как статьи, пока в памяти. Создайте lib/comments.ts:
// lib/comments.ts
export type Comment = { id: number; postSlug: string; author: string; text: string };
const comments: Comment[] = [
{ id: 1, postSlug: 'hello-nextjs', author: 'Олег', text: 'Отличная статья!' },
];
export async function getComments(postSlug: string): Promise<Comment[]> {
return comments.filter((comment) => comment.postSlug === postSlug);
}
export async function addComment(postSlug: string, author: string, text: string): Promise<Comment> {
const comment = { id: comments.length + 1, postSlug, author, text };
comments.push(comment);
return comment;
}API комментариев
Обработчик для адреса /api/posts/hello-nextjs/comments лежит в папке с динамическим сегментом:
// app/api/posts/[slug]/comments/route.ts
import { addComment, getComments } from '@/lib/comments';
type Context = { params: Promise<{ slug: string }> };
export async function GET(request: Request, { params }: Context) {
const { slug } = await params;
return Response.json(await getComments(slug));
}
export async function POST(request: Request, { params }: Context) {
const { slug } = await params;
const data = await request.json();
if (typeof data.text !== 'string' || data.text.trim() === '') {
return Response.json({ error: 'Пустой комментарий' }, { status: 400 });
}
const comment = await addComment(slug, String(data.author ?? 'Гость'), data.text);
return Response.json(comment, { status: 201 });
}Параметры адреса приходят вторым аргументом, как у страниц, — промисом. Тело запроса читает request.json().
Проверка
curl http://localhost:3000/api/posts/hello-nextjs/comments
curl -X POST http://localhost:3000/api/posts/hello-nextjs/comments -H "Content-Type: application/json" -d "{\"author\":\"Anna\",\"text\":\"Thanks\"}"Первая команда выведет массив с комментарием Олега, вторая добавит новый и вернёт его со статусом 201. Повторный GET покажет оба.
Что ещё доступно
| Задача | Как |
|---|---|
Параметры ?page=2 | new URL(request.url).searchParams.get('page') |
| Заголовки | request.headers.get('authorization') |
| Другие методы | Функции PUT, PATCH, DELETE |
В Next.js 16 обработчики GET по умолчанию не кешируются и выполняются на каждый запрос (если не включены Cache Components).
Частая ошибка
Положить route.ts и page.tsx в одну папку, например в app/posts. Один адрес не может быть и страницей, и API — Next.js сообщит о конфликте. Держите API в отдельной папке app/api/.