Що таке фільтри винятків у NestJS?
Фільтри винятків у NestJS
Фільтри винятків обробляють всі необроблені винятки в додатку. Вони перехоплюють винятки та формують HTTP-відповідь. NestJS має вбудований глобальний фільтр винятків, але ви можете створити власні фільтри для більш детального контролю.
Вбудовані HTTP винятки
NestJS надає набір стандартних винятків з коробки:
typescript
import {
BadRequestException, // 400
UnauthorizedException, // 401
ForbiddenException, // 403
NotFoundException, // 404
ConflictException, // 409
UnprocessableEntityException, // 422
InternalServerErrorException, // 500
BadGatewayException, // 502
} from '@nestjs/common';
throw new NotFoundException('Користувача не знайдено');
throw new BadRequestException('Неправильний формат електронної пошти');
throw new ConflictException('Електронна пошта вже зареєстрована');
throw new UnauthorizedException();Базовий клас HttpException
typescript
throw new HttpException('Заборонено', HttpStatus.FORBIDDEN);
// З об'єктом відповіді
throw new HttpException(
{ status: 403, error: 'Заборонено', hint: 'Зверніться до адміністратора' },
HttpStatus.FORBIDDEN
);Користувацький виняток
typescript
export class BusinessRuleException extends HttpException {
constructor(message: string, rule: string) {
super({ message, rule, statusCode: 422 }, HttpStatus.UNPROCESSABLE_ENTITY);
}
}
throw new BusinessRuleException('Не можна видалити обліковий запис з активними замовленнями', 'ACTIVE_ORDERS');Користувацький фільтр винятків
typescript
import {
ExceptionFilter, Catch, ArgumentsHost,
HttpException, HttpStatus, Logger
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
private readonly logger = new Logger(HttpExceptionFilter.name);
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const request = ctx.getRequest<Request>();
const response = ctx.getResponse<Response>();
const status = exception.getStatus();
const exceptionResponse = exception.getResponse();
const error = typeof exceptionResponse === 'string'
? { message: exceptionResponse }
: exceptionResponse as object;
this.logger.error(`${request.method} ${request.url} — ${status}`);
response.status(status).json({
...error,
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}Фільтр для всіх винятків
typescript
@Catch() // без аргументу = перехоплює все
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const message = exception instanceof HttpException
? exception.getResponse()
: 'Внутрішня помилка сервера';
response.status(status).json({
statusCode: status,
message,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}Застосування фільтрів
typescript
// На рівні методу
@Post()
@UseFilters(HttpExceptionFilter)
create(@Body() dto: CreateUserDto) { ... }
// На рівні контролера
@Controller('users')
@UseFilters(HttpExceptionFilter)
export class UsersController {}
// Глобально — main.ts
app.useGlobalFilters(new HttpExceptionFilter());
// Глобально — модуль (підтримує DI, рекомендовано)
@Module({
providers: [
{ provide: APP_FILTER, useClass: AllExceptionsFilter },
],
})Резюме
Фільтри винятків централізують форматування помилок. Використовуйте вбудовані підкласи HttpException для більшості випадків. Створіть глобальний фільтр @Catch(), щоб перехоплювати все, вести облік помилок і повертати послідовні JSON-відповіді з помилками. Реєструйте глобально через APP_FILTER, щоб скористатися впровадженням залежностей.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.