Как да използвате филтри за изключения Nest.js за справяне с грешки

Филтрите за изключения Nest.js предоставят начин за прихващане и обработка на изключения глобално или на базата на контролер.

Те ви позволяват да централизирате логиката за обработка на грешки, да форматирате отговорите за грешки и да осигурите последователно обработване на грешки във вашето приложение. Научете за филтрите за изключения и как да ги използвате за подходящо обработване на грешки в приложението.

Обработка на грешки по подразбиране в Nest.js

По подразбиране Nest.js има слой за изключения, който се занимава с всички изключения, които кодът на вашето приложение не обработва.

Когато във вашето приложение възникне необработена грешка, Nest.js я хваща и връща 500 вътрешна сървърна грешка на клиента. JSON, който Nest.js връща в този случай, изглежда така:

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

Ако обектът за грешка, който вашият код хвърля, съдържа statusCode и съобщение, Nest.js ще върне тези стойности вместо отговора по подразбиране.

За да избегнете това общо поведение и да изпратите по-смислен отговор за грешка на клиента, трябва старателно да се справите с всички грешки, които могат да възникнат във вашето приложение. Можете да постигнете това с помощта на вградени или персонализирани филтри за изключения на Nest.js.

Създаване на персонализиран филтър за изключения

За да демонстрирате процеса на създаване на персонализиран филтър за изключения, опитайте да създадете такъв, който ще обработва всички HTTP изключения.

  Пренасочете подпапка към основна папка в Apache, NGINX, IIS и Cloudflare

Започнете с файл, наречен http.exception.ts, и добавете следните импортирания към него:

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

import { Request, Response } from 'express';

Този импорт служи за следните цели.

  • ExceptionFilter: Това е интерфейс, описващ прилагането на филтър за изключения.
  • Уловка: Това е декоратор, който маркира клас като филтър за изключения на Nest.
  • ArgumentsHost: Този интерфейс предоставя методи за извличане на аргументите, предадени на манипулатор. Той ви позволява да изберете подходящия контекст на изпълнение (напр. HTTP, RPC или WebSockets), от който да извличате аргументи.
  • HttpException: Това е клас, който дефинира основното HTTP изключение на Nest.
  • Заявка и отговор: Това са интерфейсите съответно за обект на заявка и отговор на Express.js.

След това създайте клас HttpExceptionFilter, който прилага ExceptionFilter. Анотирайте го с декоратора Catch, за да посочите, че той обработва HttpExceptions:

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

След това попълнете класа с този код:

 catch(exception: HttpException, host: ArgumentsHost) {
    
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    
    const request = ctx.getRequest<Request>();

    
    const status = exception.getStatus();

    
    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message:
        exception.message
       || exception.getResponse()['message']
       || 'Internal Server Error',
    });
}

Този кодов блок извлича обектите за заявка и отговор от обекта ArgumentsHost и извлича подходяща информация от изключението. Той връща на клиента структуриран JSON обектен отговор с подробности за грешката.

Филтри за обвързващи изключения

Можете да свържете филтър за изключения към контролер или цялото ви приложение, в зависимост от вашите нужди.

  Поправете това приложение не поддържа указаната от договора грешка

За да свържете филтър за изключения глобално, първо импортирайте филтъра за изключения във вашия файл main.ts. След това предайте екземпляр на вашия филтър за изключения към метода app.useGlobalFilters:

 
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 и вашия филтър за изключения. Анотирайте вашия клас контролер с декоратора @UseFilters и предайте екземпляр на вашия филтър за изключения като аргумент на декоратора:

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

Където обвързвате вашия филтър ще определи обхвата на обработката на вашите грешки. Филтрите, свързани с контролера, ще се погрижат само за контролера, към който сте го свързали, а филтрите, свързани с приложението, ще се погрижат за цялото приложение.

Използване на вградени изключения за извеждане на грешки

Nest.js предоставя вградени класове за изключения, които можете да използвате за генериране на грешки.

Например, можете да генерирате 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`,
      });
    }
  }

Този кодов блок използва условен оператор, за да провери дали даден потребител съществува. Ако не, той извежда грешка 404, използвайки NotFoundException, като предава съобщение като аргумент.

Често срещани вградени класове за изключения

Други вградени класове изключения включват, но не се ограничават до следното.

  • BadRequestException: Извежда изключение, показващо лоша заявка с код на състоянието 400. Можете да използвате това изключение, когато заявката на клиента е невалидна или неправилно формирана и сървърът не може да я обработи поради грешка на клиента. Това обикновено означава, че клиентът трябва да промени заявката, за да я направи валидна.
  • UnauthorizedException: Извежда изключение, показващо неоторизиран достъп с код на състояние 401. Можете да използвате това изключение, когато потребителят не е удостоверен или му липсват необходимите разрешения за достъп до ресурс.
  • ForbiddenException: Извежда изключение, показващо забранен достъп с код на състояние 403. Можете да използвате това изключение, когато потребител е удостоверен, но не е упълномощен да извърши конкретно действие.
  • RequestTimeoutException: Извежда изключение, което показва, че времето за изчакване на заявката е изтекло с код на състоянието 408. Можете да използвате това изключение, когато сървър прекрати заявка, тъй като обработката й отне твърде много време.
  • ConflictException: Извежда изключение, показващо конфликт с код на състояние 409. Можете да използвате това изключение, когато има конфликт между заявката на клиента и текущото състояние на ресурса, като например когато се опитвате да създадете ресурс, който вече съществува.
  • InternalServerErrorException: Извежда изключение, показващо вътрешна грешка на сървъра с код на състояние 500. Можете да използвате това изключение, когато възникне неочаквана грешка от страната на сървъра, което показва, че сървърът не може да изпълни заявката поради вътрешен проблем.
  Как да конфигурирате настройките за поща за iPhone и iPad

Най-добри практики за обработка на грешки в Nest.js

Когато обработвате грешки в Nest.js, не забравяйте да използвате филтри за изключения, за да улавяте и обработвате изключения глобално или за всеки контролер. Можете също да създадете персонализирани филтри за конкретни типове изключения.

Освен това се уверете, че използвате подходящите вградени класове за изключения, за да хвърляте правилни и смислени грешки. Тези практики могат значително да подобрят надеждността на вашите Nest.js приложения.