Menu
CoddyTech

Intercepteurs

Fait partie de la section TypeScript et NestJS du Journey Node.js de Coddy. Leçon 23 sur 24.

Tu veux que chaque réponse indique le temps qu’elle a pris, sans toucher à chaque gestionnaire. Un intercepteur enveloppe le gestionnaire : le code avant next.handle() s’exécute avant, et le code appliqué à ce que renvoie next.handle() s’exécute après.

intercept(context: ExecutionContext, next: CallHandler) {
    console.log('before');
    return next.handle().pipe(
        tap(() => console.log('after')),
    );
}

next.handle() fournit le résultat du gestionnaire sous forme d’observable RxJS, une valeur qui arrive plus tard. .pipe(tap(...)) exécute une fonction lorsque la valeur arrive, avant que Nest ne l’envoie ; ce pipe n’a rien à voir avec les pipes de validation de Nest. Les gardes s’exécutent avant tout intercepteur : une requête refusée par une garde ne l’atteint donc jamais. Renvoie l’observable auquel le pipe a été appliqué : Nest envoie ce qu’il contient. context.switchToHttp().getResponse() fournit res, dont setHeader ajoute un en-tête.

app.useGlobalInterceptors(...) applique un intercepteur à toutes les routes ; @UseInterceptors(...) l’applique à un seul contrôleur.

challenge icon

Défi

Facile

« Exécuter » relance votre suivi en utilisant src/main.ts. Les fichiers d’entraînement séparés peuvent rester dans l’arborescence ; ce serveur ne les démarre pas.

Les clients et votre propre système de surveillance veulent savoir combien de temps a pris chaque requête. Ajoutez un en-tête de réponse, X-Response-Time, à chaque réponse réussie, sans toucher à aucune route.

  1. Ouvrez src/common/response-time.interceptor.ts. Dans la méthode intercept de ResponseTimeInterceptor, notez d’abord l’heure actuelle avec Date.now(). Le code au début de intercept s’exécute avant la méthode de la route.
  2. Récupérez le res d’Express avec context.switchToHttp().getResponse().
  3. next.handle() exécute la méthode de la route et renvoie son résultat sous la forme d’un observable RxJS : une valeur qui arrive plus tard. Continuez à le renvoyer, mais faites-le passer par tap, déjà importé depuis rxjs, en utilisant la méthode .pipe() de l’observable. La fonction que vous transmettez à tap s’exécute lorsque le résultat arrive, avant que Nest ne l’envoie. Dans cette fonction, appelez res.setHeader pour définir X-Response-Time sur le nombre de millisecondes écoulées depuis que vous avez noté l’heure, suivi de ms, par exemple 3ms. (Le .pipe() de RxJS n’a rien à voir avec les pipes de validation du chapitre 3. Il ajoute une étape à l’observable.)
  4. Dans src/main.ts, enregistrez l’intercepteur pour toute l’application avec app.useGlobalInterceptors(...), en lui transmettant une nouvelle instance de ResponseTimeInterceptor, à côté du pipe et du filtre.
  5. Les corps des réponses ne doivent pas changer. GET /tasks renvoie toujours { "items": [...], "page": 1, "total": 3, "pages": 2 }.

Essayez : envoyez GET /tasks et ouvrez l’onglet Headers de la réponse. Vous voyez X-Response-Time avec une valeur comme 0ms ou 2ms. GET /stats l’a aussi, tout comme une requête POST contenant { "title": "Buy milk" } et envoyée avec l’en-tête x-api-key: tasks-key-123. Envoyez ensuite cette requête POST sans la clé : 403, et aucun X-Response-Time. Nest exécute les guards avant les intercepteurs, donc le guard a refusé la requête avant que votre intercepteur ne démarre. Une erreur levée à l’intérieur d’une route empêche aussi l’ajout de l’en-tête, car tap ne s’exécute que lorsqu’un résultat arrive.

Essayez vous-même

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, tap } from 'rxjs';

@Injectable()
export class ResponseTimeInterceptor implements NestInterceptor {
    intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
        // Notez l’heure, laissez le gestionnaire s’exécuter, puis définissez X-Response-Time.
        return next.handle();
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de TypeScript et NestJS

Entraînez-vous par vous-même : Playground Express