Encodera

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

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

Оглавление

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

Если обработчик бросает ошибку, Fastify ловит её сам и отвечает клиенту JSON с кодом ошибки. Ваша задача — бросать ошибки с правильным кодом и при желании настроить, как они выглядят.

Ошибка с кодом

Код ответа Fastify берёт из свойства statusCode ошибки. Без него получится 500:

// src/routes/posts.js
app.get('/posts/:id', async (request) => {
  const post = app.posts.find((item) => item.id === request.params.id);
  if (!post) {
    const error = new Error('Статья не найдена');
    error.statusCode = 404;
    throw error;
  }
  return post;
});

/posts/99 вернёт {"statusCode":404,"error":"Not Found","message":"Статья не найдена"}.

@fastify/sensible

Создавать ошибку вручную долго. Официальный плагин @fastify/sensible добавляет готовые функции:

npm install @fastify/sensible
// src/app.js
import sensible from '@fastify/sensible';
 
app.register(sensible);

Теперь в любом маршруте доступны app.httpErrors:

// src/routes/posts.js
app.get('/posts/:id', async (request) => {
  const post = app.posts.find((item) => item.id === request.params.id);
  if (!post) {
    throw app.httpErrors.notFound('Статья не найдена');
  }
  return post;
});

Ответ тот же, а код короче. Есть и другие: badRequest() — 400, unauthorized() — 401, forbidden() — 403, conflict() — 409.

Свой обработчик ошибок

setErrorHandler задаёт функцию, через которую проходят все ошибки. Добавьте в src/app.js:

// src/app.js
app.setErrorHandler((error, request, reply) => {
  const statusCode = error.statusCode ?? 500;
 
  if (statusCode >= 500) {
    request.log.error(error);
    return reply.code(500).send({ error: 'Внутренняя ошибка сервера' });
  }
 
  return reply.code(statusCode).send({ error: error.message });
});

Ошибки клиента (код 4xx) возвращаются с исходным сообщением, а ошибки сервера записываются в лог и отдаются клиенту без подробностей. Ошибки проверки схемы тоже приходят сюда — с кодом 400 и свойством error.validation.

Страница 404

Для адресов без маршрута есть отдельный обработчик:

// src/app.js
app.setNotFoundHandler((request, reply) => {
  return reply.code(404).send({ error: `Адрес ${request.url} не найден` });
});

http://localhost:3000/nothing вернёт {"error":"Адрес /nothing не найден"}.

Где действуют обработчики

Оба метода подчиняются инкапсуляции: вызванные в плагине, они действуют только на его маршруты. Например, у раздела /admin может быть своя страница 404.

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

Отдавать клиенту error.message для любых ошибок опасно: сообщение ошибки базы данных или кода может раскрыть имена таблиц, пути к файлам и другие детали. Для кода 500 отвечайте общей фразой, а подробности пишите в лог, как в примере выше.

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

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