Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Параметры, запрос и тело в обработчиках

Обработчику 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).

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.