Comment utiliser les filtres d’exception Nest.js pour gérer les erreurs

Les filtres d’exceptions Nest.js permettent d’intercepter et de gérer les exceptions globalement ou par contrôleur.

Ils vous permettent de centraliser la logique de gestion des erreurs, de formater les réponses aux erreurs et de fournir une gestion cohérente des erreurs dans toute votre application. Découvrez les filtres d’exception et comment les utiliser pour gérer de manière appropriée les erreurs d’application.

Gestion des erreurs par défaut dans Nest.js

Par défaut, Nest.js dispose d’une couche d’exceptions qui traite toutes les exceptions que votre code d’application ne gère pas.

Lorsqu’une erreur non gérée se produit dans votre application, Nest.js la détecte et renvoie une erreur de serveur interne 500 au client. Le JSON renvoyé par Nest.js dans ce cas ressemble à ceci :

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

Si l’objet d’erreur généré par votre code contient un statusCode et un message, Nest.js renverra ces valeurs au lieu de la réponse par défaut.

Pour éviter ce comportement générique et envoyer une réponse d’erreur plus significative au client, vous devez gérer avec diligence toutes les erreurs pouvant survenir dans votre application. Vous pouvez y parvenir à l’aide des filtres d’exception intégrés ou personnalisés de Nest.js.

Création d’un filtre d’exception personnalisé

Pour illustrer le processus de création d’un filtre d’exception personnalisé, essayez d’en créer un qui gérera toutes les exceptions HTTP.

Commencez par un fichier appelé http.exception.ts et ajoutez-y les importations suivantes :

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

import { Request, Response } from 'express';

Ces importations répondent aux objectifs suivants.

  • ExceptionFilter : Il s’agit d’une interface décrivant l’implémentation d’un filtre d’exception.
  • Catch : il s’agit d’un décorateur qui marque une classe comme filtre d’exception Nest.
  • ArgumentsHost : Cette interface fournit des méthodes pour récupérer les arguments passés à un gestionnaire. Il vous permet de choisir le contexte d’exécution approprié (par exemple, HTTP, RPC ou WebSockets) à partir duquel récupérer les arguments.
  • HttpException : il s’agit d’une classe qui définit l’exception HTTP Nest de base.
  • Requête et réponse : ce sont les interfaces pour un objet de requête et de réponse Express.js, respectivement.

Créez ensuite une classe, HttpExceptionFilter, qui implémente ExceptionFilter. Annotez-le avec le décorateur Catch pour indiquer qu’il gère les HttpExceptions :

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

Ensuite, remplissez la classe avec ce code :

 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',
    });
}

Ce bloc de code récupère les objets de requête et de réponse de l’objet ArgumentsHost et extrait les informations pertinentes de l’exception. Il renvoie au client une réponse d’objet JSON structurée, avec des détails sur l’erreur.

Filtres d’exception de liaison

Vous pouvez lier un filtre d’exception à un contrôleur ou à l’ensemble de votre application, en fonction de vos besoins.

Pour lier un filtre d’exception globalement, importez d’abord le filtre d’exception dans votre fichier main.ts. Ensuite, transmettez une instance de votre filtre d’exception à la méthode 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();

Pour lier une exception à un contrôleur, importez le décorateur UseFilters et votre filtre d’exception. Annotez votre classe de contrôleur avec le décorateur @UseFilters et transmettez une instance de votre filtre d’exception comme argument au décorateur :

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

L’endroit où vous liez votre filtre déterminera la portée de votre gestion des erreurs. Les filtres liés au contrôleur ne s’adresseront qu’au contrôleur auquel vous l’avez lié, et les filtres liés à l’application s’adresseront à l’ensemble de l’application.

Utilisation d’exceptions intégrées pour générer des erreurs

Nest.js fournit des classes d’exception intégrées que vous pouvez utiliser pour générer des erreurs.

Par exemple, vous pouvez générer des erreurs de code d’état 404 avec la classe NotFoundException :

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

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

Ce bloc de code utilise une instruction conditionnelle pour vérifier si l’utilisateur donné existe. Sinon, il génère une erreur 404 en utilisant NotFoundException, en passant un message en argument.

Classes d’exceptions intégrées courantes

Les autres classes d’exceptions intégrées incluent, sans s’y limiter, les suivantes.

  • BadRequestException : lève une exception indiquant une mauvaise demande avec un code d’état de 400. Vous pouvez utiliser cette exception lorsque la demande du client est invalide ou mal formée et que le serveur ne peut pas la traiter en raison de l’erreur du client. Cela implique généralement que le client doit modifier la demande pour la rendre valide.
  • UnauthorizedException : lève une exception indiquant un accès non autorisé avec un code d’état de 401. Vous pouvez utiliser cette exception lorsqu’un utilisateur n’est pas authentifié ou ne dispose pas des autorisations nécessaires pour accéder à une ressource.
  • ForbiddenException : lève une exception indiquant un accès interdit avec un code d’état de 403. Vous pouvez utiliser cette exception lorsqu’un utilisateur est authentifié mais n’est pas autorisé à effectuer une action spécifique.
  • RequestTimeoutException : lève une exception indiquant que la demande a expiré avec un code d’état de 408. Vous pouvez utiliser cette exception lorsqu’un serveur met fin à une demande car son traitement a pris trop de temps.
  • ConflictException : lève une exception indiquant un conflit avec un code d’état de 409. Vous pouvez utiliser cette exception en cas de conflit entre la demande du client et l’état actuel de la ressource, par exemple lorsque vous essayez de créer une ressource qui existe déjà.
  • InternalServerErrorException : lève une exception indiquant une erreur de serveur interne avec un code d’état de 500. Vous pouvez utiliser cette exception lorsqu’une erreur inattendue se produit côté serveur, indiquant que le serveur ne peut pas répondre à la demande en raison d’un problème interne.

Bonnes pratiques pour la gestion des erreurs dans Nest.js

Lors de la gestion des erreurs dans Nest.js, veillez à utiliser des filtres d’exception pour détecter et gérer les exceptions globalement ou par contrôleur. Vous pouvez également créer des filtres personnalisés pour des types d’exceptions spécifiques.

De plus, assurez-vous d’utiliser les classes d’exception intégrées appropriées pour générer des erreurs appropriées et significatives. Ces pratiques peuvent améliorer considérablement la fiabilité de vos applications Nest.js.