Гид по технологиям

Фильтры исключений в Nest.js — обработка ошибок

6 min read Backend Обновлено 30 Dec 2025
Фильтры исключений в Nest.js — обработка ошибок
Фильтры исключений в Nest.js — обработка ошибок

Логотип Nest.js: красный силуэт кошачьей головы на фоне платы компьютера

Что такое фильтры исключений

Фильтр исключений — компонент, который перехватывает исключения в точке выхода из обработчика и формирует ответ клиенту. Коротко: фильтр получает исключение и аргументы выполнения, и решает, как вернуть ошибку.

Определение в одну строку: ExceptionFilter — интерфейс с методом catch(exception, host), где host даёт доступ к Request/Response.

Важно: фильтры не заменяют валидацию, авторизацию или структуру данных — они служат для управления ошибками, логирования и приведения ответа к единому формату.

Стандартная обработка ошибок в Nest.js

По умолчанию Nest.js ловит необработанные исключения и возвращает 500 Internal Server Error. Типичный ответ выглядит так:

{
  "statusCode": 500,
  "message": "Internal server error"
}

Если брошенное исключение содержит statusCode и message (например, стандартные HttpException-классы), Nest.js использует их вместо дефолтного ответа.

Чтобы заменить поведение по умолчанию и дать клиенту более осмысленный ответ, используйте встроенные или собственные фильтры исключений.

Создание кастомного фильтра исключений

Пример: фильтр, обрабатывающий все HttpException.

Создайте файл http.exception.ts и добавьте импорты:

import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
} from '@nestjs/common';

import { Request, Response } from 'express';

Назначение импортов:

  • ExceptionFilter: интерфейс для реализации фильтра.
  • Catch: декоратор, помечающий класс как фильтр.
  • ArgumentsHost: позволяет получить контекст выполнения (HTTP, RPC, WebSockets).
  • HttpException: базовый HTTP-исключение Nest.
  • Request и Response: интерфейсы Express.

Добавьте класс, помеченный декоратором Catch:

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {}

Заполните метод catch этим кодом:

catch(exception: HttpException, host: ArgumentsHost) {
  // Получаем HTTP-контекст и объекты request/response
  const ctx = host.switchToHttp();
  const response = ctx.getResponse();
  const request = ctx.getRequest();

  // Статус из исключения
  const status = exception.getStatus();

  // Формируем структурированный JSON-ответ
  response.status(status).json({
    statusCode: status,
    timestamp: new Date().toISOString(),
    path: request.url,
    message:
      exception.message ||
      (exception.getResponse() as any)['message'] ||
      'Internal Server Error',
  });
}

Этот фильтр извлекает request/response из ArgumentsHost и формирует единый JSON с полями statusCode, timestamp, path и message.

Важно: не выводите в production полные стек-трейсы в ответах — логируйте детали, но отправляйте клиенту безопасное сообщение.

Привязка фильтров

Можно привязывать фильтры на уровне приложения или контроллера.

Чтобы зарегистрировать глобально, импортируйте фильтр в main.ts и вызовите app.useGlobalFilters:

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './exception/http.exception';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Привязка фильтра к приложению
  app.useGlobalFilters(new HttpExceptionFilter());

  await app.listen(4050);
}

bootstrap();

Чтобы привязать к конкретному контроллеру, используйте декоратор @UseFilters:

@Controller()
@UseFilters(new HttpExceptionFilter())
export class AppController {}

Scope влияет на объём покрытия: глобальный фильтр обслуживает все контроллеры и middleware-цепочки, тогда как фильтр, привязанный к контроллеру, действует только для вызовов внутри этого контроллера.

Использование встроенных исключений для генерации ошибок

Nest.js предоставляет набор готовых классов исключений, которые устанавливают соответствующие HTTP-статусы.

Пример: выбрасываем 404 с помощью NotFoundException:

getUserById(id: number) {
  const user = users.find((user) => user.id === id);

  if (!user) {
    throw new NotFoundException({
      message: `User with id ${id} not found`,
    });
  }
}

Список часто используемых встроенных классов:

  • BadRequestException — 400. Используйте при неверном запросе или ошибках валидации.
  • UnauthorizedException — 401. Когда пользователь не аутентифицирован.
  • ForbiddenException — 403. Когда пользователь аутентифицирован, но не авторизован.
  • NotFoundException — 404. Ресурс не найден.
  • RequestTimeoutException — 408. Запрос превысил время ожидания.
  • ConflictException — 409. Конфликт состояния, например, дублирование ресурса.
  • InternalServerErrorException — 500. Внутренняя ошибка сервера.

Использование встроенных классов упрощает создание предсказуемых ответов и интеграцию с фильтрами, которые опираются на getStatus().

Лучшие практики обработки ошибок

  • Централизация: держите общий формат ответов в глобальном фильтре.
  • Разделение обязанностей: валидация — пайпы, авторизация — гварды, а ошибки — фильтры.
  • Не проливайте детали в клиентские ответы: оставляйте стек и чувствительные данные в логах.
  • Корреляция: добавляйте correlationId (X-Request-Id) и возвращайте его в ответе для отладки.
  • Логирование: логируйте исключения с уровнем и метаданными (маршрут, пользователь, id запроса).
  • Мониторинг: интегрируйте Sentry/Datadog для трекинга ошибок и алертов.
  • Тестируемость: покрывайте фильтры юнит-тестами и интеграционными тестами, проверяйте формат ответа для каждого типа исключения.
  • Локализация: если API ориентирован на пользователей, локализуйте сообщения ошибок на нужные языки.

Альтернативные подходы и когда использовать их

  • Interceptors (перехватчики): полезны для преобразования успешных ответов и глобальной трансформации, но не заменяют фильтры при обработке исключений.
  • Middleware: подходит для логирования и добавления заголовков, но они работают до контроллера и не всегда видят исключения, возникающие позже.
  • Pipes: оптимальны для валидации/трансформации данных до контроллера — бросают BadRequestException при ошибках валидации.
  • Guards: блокируют доступ к эндпойнтам (401/403) — используются вместе с фильтрами для возврата корректных ошибок.

Когда фильтры не помогут:

  • Ошибки на уровне инфраструктуры (база данных, сеть) требуют ретрайев и fallback-логики, которые реализуются в сервисах/интеграциях.
  • Если вы хотите изменять успешный результат (2xx), используйте Interceptors.

Когда кастомный фильтр может навредить

  • Если вы теряете оригинальную семантику исключения (заменяете полезный статус на 500).
  • Если фильтр пробрасывает приватные данные в ответе.
  • Если фильтр слишком тяжёлый и выполняет много синхронной работы (может замедлить отклики).

Руководство по внедрению (мини-методология)

  1. Определите формат общего ответа об ошибке (поля: statusCode, message, timestamp, path, correlationId).
  2. Реализуйте глобальный HttpExceptionFilter и логирование исключений.
  3. Добавьте в pipeline middleware генерацию correlationId.
  4. Покройте юнит-тестами поведение фильтра для разных типов исключений.
  5. Интегрируйте мониторинг и алерты (Sentry/Prometheus).
  6. Проведите нагрузочное тестирование, чтобы убедиться, что фильтр не становится узким местом.

Чеклист ролей

Для разработчика:

  • Реализован общий формат ошибок
  • Написаны юнит-тесты для фильтра
  • Не возвращаются стек-трейсы в production

Для QA:

  • Проверены ответы на 400/401/403/404/500
  • Проверена корреляция request-id в логах и ответах

Для оператора/DevOps:

  • Настроены алерты на увеличение числа 5xx
  • Интеграция с Sentry/Tracing настроена

Фактбокс — ключевые статусы

  • 400 — Bad Request
  • 401 — Unauthorized
  • 403 — Forbidden
  • 404 — Not Found
  • 408 — Request Timeout
  • 409 — Conflict
  • 500 — Internal Server Error

Критерии приёмки

  • API возвращает предопределённый JSON-формат ошибок для всех проверенных сценариев.
  • Логи содержат correlationId и достаточные метаданные для отладки.
  • Никакие чувствительные данные не возвращаются в ответах клиентов.
  • Юнит- и интеграционные тесты покрывают основные исключения.

Примеры тестовых сценариев и критерии приёмки

  • Запрос с невалидным телом должен вернуть 400 и корректный JSON-ответ.
  • Доступ без токена к защищённому маршруту должен вернуть 401.
  • Запрос к отсутствующему ресурсу должен вернуть 404 с понятным message.
  • Исключение в сервисе (необработанное) должно логироваться и возвращать 500 без приватных данных.

Примеры отказа и варианты обхода

  • Если клиент требует детальных ошибок для отладки, предоставьте режим “debug” только для локальной среды и не включайте его в production.
  • Если приложение использует GraphQL, используйте соответствующие фильтры исключений для GraphQL-контекста — HTTP-фильтры не всегда применимы.

Безопасность и приватность

Не возвращайте в ответах внутренние сообщения ошибок, стек-трейсы или данные конфигурации. Логируйте чувствительные данные в защищённом хранилище с ограниченным доступом. При работе с персональными данными соблюдайте требования GDPR/локального законодательства: храните минимальный набор логов и маскируйте персональные идентификаторы в ошибках.

Короткий глоссарий

  • ExceptionFilter: интерфейс для фильтров исключений.
  • ArgumentsHost: объект, дающий доступ к контексту исполнения.
  • HttpException: базовый класс для HTTP-исключений в Nest.js.
  • Interceptor: компонент для перехвата и трансформации ответов.

Decision flowchart

flowchart TD
  A[Запрос пришёл] --> B{Ошибка возникла в контроллере?}
  B -- Нет --> C[Возврат успешного ответа]
  B -- Да --> D{Это HttpException?}
  D -- Да --> E[Пойман HttpExceptionFilter]
  D -- Нет --> F[Пойман глобальным фильтром как 500]
  E --> G[Логирование, ответ с кодом и message]
  F --> G
  G --> H[Мониторинг/Алерт]

Заключение

Фильтры исключений — ключевой инструмент в Nest.js для согласованной, безопасной и наблюдаемой обработки ошибок. Комбинируйте их с пайпами, гвардами и инструментами мониторинга, следите за тем, чтобы клиентам возвращались информативные, но безопасные сообщения. Правильно реализованная обработка ошибок снижает время на диагностику и повышает надёжность системы.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Взлом Wi‑Fi: методы и защита
Кибербезопасность

Взлом Wi‑Fi: методы и защита

Суммирование в Google Sheets — числа, ячейки, матрицы
Google Таблицы

Суммирование в Google Sheets — числа, ячейки, матрицы

Разблокировка iPhone с Apple Watch
Гаджеты

Разблокировка iPhone с Apple Watch

Импорт и экспорт данных в Excel
Excel

Импорт и экспорт данных в Excel

Автоматизация Android для длительной работы батареи
Android.

Автоматизация Android для длительной работы батареи

Папка автозагрузки Windows — где и как управлять
Windows

Папка автозагрузки Windows — где и как управлять