Исключения и фильтры исключений
В NestJS ошибку не отправляют вручную через объект ответа — её бросают как исключение. Встроенный обработчик ловит его и сам формирует JSON с кодом ответа. Фильтр исключений позволяет заменить этот обработчик своим, если нужен другой формат ошибок.
Встроенные исключения
Сейчас запрос несуществующей статьи возвращает пустой ответ с кодом 200. Правильный ответ — 404. Бросьте исключение в сервисе:
// src/posts/posts.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { Post } from './entities/post.entity';
@Injectable()
export class PostsService {
private posts: Post[] = [];
findOne(id: number): Post {
const post = this.posts.find((item) => item.id === id);
if (!post) {
throw new NotFoundException(`Статья ${id} не найдена`);
}
return post;
}
}Откройте /posts/999 — придёт ответ с кодом 404:
{
"message": "Статья 999 не найдена",
"error": "Not Found",
"statusCode": 404
}Метод теперь всегда возвращает Post, а не Post | undefined, — проверять результат в контроллере не нужно.
| Исключение | Код |
|---|---|
BadRequestException | 400 |
UnauthorizedException | 401 |
ForbiddenException | 403 |
NotFoundException | 404 |
ConflictException | 409 |
InternalServerErrorException | 500 |
Все они наследуют класс HttpException. Для редкого кода подойдёт он сам: throw new HttpException('Слишком много запросов', 429).
Фильтр исключений
Фильтр — класс, который ловит исключения и сам отправляет ответ. Пусть все ошибки блога содержат адрес запроса и время:
nest g filter common/filters/http-exception --flat// src/common/filters/http-exception.filter.ts
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const http = host.switchToHttp();
const request = http.getRequest<Request>();
const response = http.getResponse<Response>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
message: exception.message,
path: request.url,
timestamp: new Date().toISOString(),
});
}
}@Catch(HttpException) говорит, какие исключения ловит фильтр. host.switchToHttp() даёт доступ к обычным объектам запроса и ответа Express.
Подключение фильтра
Для всего приложения — в src/main.ts:
// src/main.ts
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
app.useGlobalFilters(new HttpExceptionFilter());Для одного контроллера или метода — декоратором @UseFilters(HttpExceptionFilter). Снова откройте /posts/999: в ответе появятся поля path со значением /posts/999 и timestamp.
Частая ошибка
Если бросить обычную ошибку throw new Error('Статья не найдена'), NestJS не знает её кода и отвечает 500 с текстом Internal server error. Клиент не поймёт, что статьи просто нет. Для ожидаемых ситуаций всегда бросайте наследников HttpException, а 500 оставьте для настоящих сбоев.