Interceptory
Część sekcji TypeScript i NestJS ścieżki Node.js w Coddy. Lekcja 23 z 24.
Chcesz, aby każda odpowiedź informowała, ile czasu to zajęło, bez modyfikowania każdego handlera. Interceptor otacza handler: kod przed next.handle() wykonuje się przed nim, a kod uruchamiany na tym, co zwraca next.handle(), wykonuje się po nim.
intercept(context: ExecutionContext, next: CallHandler) {
console.log('before');
return next.handle().pipe(
tap(() => console.log('after')),
);
}next.handle() zwraca wynik handlera jako observable RxJS, czyli wartość, która pojawia się później. .pipe(tap(...)) uruchamia funkcję, gdy pojawi się wartość, zanim Nest ją wyśle; to pipe nie ma nic wspólnego z potokami walidacji Nest. Guardy uruchamiają się przed każdym interceptorem, więc żądanie odrzucone przez guarda nigdy do niego nie dotrze. Zwróć observable z potokiem: Nest wysyła to, co on zawiera. context.switchToHttp().getResponse() zwraca res, którego setHeader dodaje nagłówek.
app.useGlobalInterceptors(...) stosuje interceptor do każdej trasy; @UseInterceptors(...) — do jednego kontrolera.
Wyzwanie
ŁatwyUruchom ponownie swój tracker, używając src/main.ts. Oddzielne pliki ćwiczeniowe mogą pozostać w drzewie; ten serwer ich nie uruchamia.
Klienci i Twoje własne narzędzia monitorujące chcą wiedzieć, ile czasu zajęło każde żądanie. Dodaj nagłówek odpowiedzi X-Response-Time do każdej pomyślnej odpowiedzi, nie zmieniając żadnej trasy.
- Otwórz
src/common/response-time.interceptor.ts. W metodzieinterceptklasyResponseTimeInterceptornajpierw zapisz bieżący czas za pomocąDate.now(). Kod na początku metodyintercepturuchamia się przed metodą trasy. - Pobierz
resExpressa za pomocącontext.switchToHttp().getResponse(). next.handle()uruchamia metodę trasy i zwraca jej wynik jako obserwowalny obiekt RxJS: wartość, która pojawia się później. Nadal go zwracaj, ale przekaż go przeztap, który jest już zaimportowany zrxjs, za pomocą metody.pipe()obserwowalnego obiektu. Funkcja przekazana dotapuruchamia się, gdy pojawi się wynik, przed wysłaniem go przez Nest. W tej funkcji wywołajres.setHeader, aby ustawićX-Response-Timena liczbę milisekund od zapisania czasu, po której następujems, na przykład3ms. (.pipe()w RxJS nie ma nic wspólnego z potokami walidacyjnymi z rozdziału 3. Dodaje krok do łańcucha obserwowalnego obiektu.)- W pliku
src/main.tszarejestruj interceptor dla całej aplikacji za pomocąapp.useGlobalInterceptors(...), przekazując nowy obiektResponseTimeInterceptor, obok potoku i filtra. - Treść odpowiedzi nie może się zmienić.
GET /tasksnadal zwraca{ "items": [...], "page": 1, "total": 3, "pages": 2 }.
Wypróbuj: wyślij GET /tasks i otwórz kartę Nagłówki odpowiedzi. Zobaczysz X-Response-Time z wartością taką jak 0ms lub 2ms. Jest on również obecny w GET /stats oraz w żądaniu POST z treścią { "title": "Buy milk" }, wysłanym z nagłówkiem x-api-key: tasks-key-123. Następnie wyślij to żądanie POST bez klucza: 403 i brak X-Response-Time. Nest uruchamia strażników przed interceptorami, więc strażnik odrzucił żądanie, zanim uruchomił się Twój interceptor. Błąd zgłoszony wewnątrz trasy również pomija ten nagłówek, ponieważ tap uruchamia się tylko wtedy, gdy pojawi się wynik.
Spróbuj swoich sił
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> {
// Zanotuj czas, pozwól wykonać się handlerowi, a następnie ustaw X-Response-Time.
return next.handle();
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji TypeScript i NestJS
1Podstawy Nest
Klasy i metodyWitaj, NestRejestrowanie kontrolera4Strażnicy, filtry i interceptory
StrażnicyPoćwicz samodzielnie: Edytor online Express