Encodera

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

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

Оглавление

Обработка ошибок

Если маршрут не найден, Hono отвечает текстом 404 Not Found, а если в коде возникло исключение — текстом Internal Server Error с кодом 500. Для API это неудобно: клиент ждёт JSON. Hono позволяет заменить оба ответа и выбрасывать ошибки с нужным кодом прямо из обработчика.

Неизвестный адрес

В src/index.ts, после подключения групп маршрутов, добавьте:

// src/index.ts
app.notFound((c) => {
  return c.json({ error: `Адрес ${c.req.path} не найден` }, 404)
})

Откройте http://localhost:3000/nothing — придёт JSON {"error":"Адрес /nothing не найден"} с кодом 404.

HTTPException

Чтобы прервать обработку с понятным кодом, выбросьте HTTPException:

// src/routes/posts.ts
import { HTTPException } from 'hono/http-exception'
 
posts.get('/:id', (c) => {
  const post = allPosts.find((p) => p.id === Number(c.req.param('id')))
 
  if (!post) {
    throw new HTTPException(404, { message: 'Статья не найдена' })
  }
 
  return c.json(post)
})

Здесь allPosts — массив статей из прошлых уроков. Запрос /posts/99 вернёт код 404 и текст «Статья не найдена». Исключение удобно выбрасывать из вспомогательных функций и middleware, где вернуть ответ через return нельзя.

Общий обработчик ошибок

app.onError() получает каждую ошибку, которую не перехватил обработчик:

// src/index.ts
import { HTTPException } from 'hono/http-exception'
 
app.onError((err, c) => {
  if (err instanceof HTTPException) {
    return c.json({ error: err.message }, err.status)
  }
 
  console.error(err)
  return c.json({ error: 'Внутренняя ошибка сервера' }, 500)
})

Теперь /posts/99 вернёт JSON {"error":"Статья не найдена"} с кодом 404. Любая другая ошибка, например опечатка в коде, запишется в терминал, а клиент получит короткое сообщение с кодом 500.

Где что срабатывает

СитуацияКто отвечает
нет подходящего маршрутаapp.notFound()
throw new HTTPException(...)app.onError()
любая другая ошибка в кодеapp.onError()
ошибка проверки zodсам валидатор, код 400

Обработчики notFound и onError задают у главного приложения в src/index.ts: тогда они работают и для групп, подключённых через app.route().

Проверка

curl -i http://localhost:3000/posts/99

В ответе будет строка HTTP/1.1 404 Not Found и JSON с сообщением.

Частая ошибка

В onError отдают клиенту текст любой ошибки:

// src/index.ts
app.onError((err, c) => c.json({ error: err.message }, 500))

Так наружу попадают внутренние подробности: текст SQL-запроса, пути к файлам, имена таблиц. Показывайте клиенту только сообщения HTTPException, которые вы написали сами, а остальное пишите в журнал.

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

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