Параметры, запрос и тело в обработчиках
Обработчику API нужны данные из запроса: номер статьи из адреса, строка поиска после знака вопроса, поля формы. Nitro даёт для этого функции getRouterParam, getQuery и readBody, а функция createError отвечает клиенту ошибкой с нужным кодом.
Общий список статей
Несколько обработчиков будут работать с одним списком. Создайте файл server/utils/posts.ts:
// server/utils/posts.ts
export const posts = [
{ id: 1, title: 'Первый пост', text: 'Привет, мир!' },
{ id: 2, title: 'Изучаем Nuxt', text: 'Страницы из файлов.' }
]Всё, что экспортируется из server/utils/, доступно в обработчиках без импорта. Список живёт в памяти сервера и сбрасывается при перезапуске — в следующем уроке статьи переедут на диск.
Параметр адреса
Создайте server/api/posts/[id].get.ts:
// server/api/posts/[id].get.ts
export default defineEventHandler((event) => {
const id = Number(getRouterParam(event, 'id'))
const post = posts.find((p) => p.id === id)
if (!post) {
throw createError({ statusCode: 404, message: 'Статья не найдена' })
}
return post
})getRouterParam возвращает часть адреса из квадратных скобок. Адрес /api/posts/1 вернёт первую статью, а /api/posts/99 — ответ с кодом 404 и сообщением «Статья не найдена».
Строка запроса
Добавьте поиск в server/api/posts.get.ts:
// server/api/posts.get.ts
export default defineEventHandler((event) => {
const { search } = getQuery(event)
if (typeof search === 'string' && search !== '') {
const word = search.toLowerCase()
return posts.filter((p) => p.title.toLowerCase().includes(word))
}
return posts
})getQuery возвращает объект с параметрами после ?. Адрес /api/posts?search=nuxt вернёт только статью «Изучаем Nuxt».
Тело запроса
Новая статья приходит в теле запроса POST. Создайте server/api/posts.post.ts:
// server/api/posts.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody<{ title?: string; text?: string }>(event)
if (!body.title || !body.text) {
throw createError({ statusCode: 400, message: 'Заполните заголовок и текст' })
}
const post = {
id: Math.max(0, ...posts.map((p) => p.id)) + 1,
title: body.title,
text: body.text
}
posts.push(post)
setResponseStatus(event, 201)
return post
})readBody читает тело запроса и разбирает JSON. Код 201 означает «создано». Проверьте обработчик из терминала:
curl -X POST http://localhost:3000/api/posts -H "Content-Type: application/json" -d "{\"title\":\"Третий пост\",\"text\":\"Текст\"}"В ответ придёт новая статья с id 3, и она появится по адресу /api/posts. Форму на сайте для этого запроса вы сделаете в главе о загрузке данных.
Функции запроса
| Функция | Что возвращает |
|---|---|
getRouterParam(event, 'id') | Параметр из адреса, строку |
getQuery(event) | Объект параметров после ? |
await readBody(event) | Тело запроса |
getHeader(event, 'user-agent') | Заголовок запроса |
getCookie(event, 'token') | Значение cookie |
Частая ошибка
readBody возвращает обещание. Если забыть await, в переменной окажется Promise, у которого нет поля title, и проверка вернёт ошибку 400 даже на правильный запрос. Делайте обработчик async и всегда пишите await readBody(event).