Skip to main content

Що таке Exception Filter?

Що таке Exception Filter

Exception Filter (фільтр винятків) - це клас, який перехоплює помилки (exceptions), що виникають у процесі обробки запиту, і керує тим, яку відповідь отримає клієнт.

Якщо контролер чи сервіс кидає виняток (throw new Error() / throw new HttpException()), фільтр може впіймати його, перетворити на читабельну відповідь і повернути клієнту структурований JSON.

Приклад без фільтра

javascript
@Controller('users') export class UsersController { @Get(':id') findOne(@Param('id') id: string) { if (id !== '1') { throw new NotFoundException('Користувача не знайдено'); } return { id: 1, name: 'John' }; } }

NestJS за замовчуванням загортає стандартні винятки (HttpException) у зручну відповідь вигляду:

javascript
{ "statusCode": 404, "message": "Користувача не знайдено", "error": "Not Found" }

Але якщо кинути нестандартну помилку (throw new Error('Помилка БД')), Nest не знає, як її оформити - і поверне 500 без форматування.

Ось тут і знадобиться Exception Filter.

Приклад кастомного Exception Filter

javascript
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, } from '@nestjs/common'; @Catch() // перехоплює УСІ помилки export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); const request = ctx.getRequest(); const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR; const message = exception instanceof HttpException ? exception.getResponse() : 'Internal server error'; response.status(status).json({ statusCode: status, message, path: request.url, timestamp: new Date().toISOString(), }); } }

Підключення Exception Filter

1. Локально (на контролер чи метод):

javascript
@UseFilters(AllExceptionsFilter) @Controller('users') export class UsersController { @Get() findAll() { throw new Error('Щось пішло не так'); } }

2. Глобально (на весь застосунок):

javascript
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { AllExceptionsFilter } from './filters/all-exceptions.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalFilters(new AllExceptionsFilter()); await app.listen(3000); } bootstrap();

Тепер будь-який кинутий Exception буде впійманий фільтром, і клієнт отримає акуратну, однакову відповідь.

Приклад фільтра для конкретного типу помилок

Можна перехоплювати лише певні типи винятків.

javascript
import { Catch, ExceptionFilter, ArgumentsHost, NotFoundException } from '@nestjs/common'; @Catch(NotFoundException) export class NotFoundFilter implements ExceptionFilter { catch(exception: NotFoundException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); response.status(404).json({ error: 'Ресурс не знайдено', details: exception.message, }); } }

Такий фільтр спрацює лише на throw new NotFoundException().

Що робить ArgumentsHost

ArgumentsHost - це універсальний об'єкт, який дає доступ до контексту виконання: HTTP, WebSocket чи RPC.

Для HTTP-запиту:

javascript
const ctx = host.switchToHttp(); const request = ctx.getRequest(); const response = ctx.getResponse();

За його допомогою можна отримати доступ до:

  • запиту (request);
  • відповіді (response);
  • контексту виконання (context).

Порядок роботи фільтрів

  1. Контролер чи сервіс кидає виняток.
  2. Nest намагається знайти відповідний Exception Filter.
  3. Якщо фільтр знайдено → він обробляє помилку й формує відповідь.
  4. Якщо ні → Nest використовує вбудований фільтр за замовчуванням.

Часті застосування

ПризначенняПриклад
Уніфікований формат помилокОднакова JSON-відповідь для всіх винятків
Обробка бізнес-помилок"Недостатньо прав", "Акаунт заблоковано"
Помилки БДПерехоплення SQL/Prisma помилок і повернення дружнього повідомлення
Різні контекстиМожна писати фільтри для WebSocket, GraphQL, RPC

Приклад: фільтр для Prisma

javascript
@Catch(Prisma.PrismaClientKnownRequestError) export class PrismaExceptionFilter implements ExceptionFilter { catch(exception: Prisma.PrismaClientKnownRequestError, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); if (exception.code === 'P2002') { response.status(409).json({ error: 'Conflict', message: 'Duplicate entry', }); } else { response.status(500).json({ error: 'Database error', message: exception.message, }); } } }

Підсумок

ПоняттяОпис
Exception FilterМеханізм для перехоплення й обробки винятків
ІнтерфейсExceptionFilter з методом catch(exception, host)
Декоратор@Catch() - вказує тип винятків
ЗастосуванняЧерез @UseFilters() чи app.useGlobalFilters()
МетаЦентралізована обробка помилок і форматування відповідей
За замовчуваннямNest має вбудований фільтр для HttpException
РозширенняМожна писати власні для БД, авторизації, логування тощо

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.