Menu
CoddyTech

Interceptor’lar

Coddy'nin Node.js Journey'sinin TypeScript ve NestJS bölümünün bir parçası. Ders 23 / 24.

Her yanıtın, her işleyiciye tek tek dokunmadan ne kadar sürdüğünü belirtmesini istiyorsun. Bir interceptor, işleyiciyi sarar: next.handle() öncesindeki kod ondan önce çalışır, next.handle() çağrısının döndürdüğü sonuç üzerindeki kod ise ondan sonra çalışır.

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

next.handle(), işleyicinin sonucunu bir RxJS observable'ı, yani daha sonra gelen bir değer olarak verir. .pipe(tap(...)), değer geldiğinde Nest onu göndermeden önce bir işlev çalıştırır; bu pipe, Nest'in doğrulama pipe'larıyla ilgili değildir. Guard'lar tüm interceptor'lardan önce çalışır; bu nedenle bir guard'ın reddettiği istek interceptor'a asla ulaşmaz. Pipe uygulanmış observable'ı döndür: Nest onun taşıdığı değeri gönderir. context.switchToHttp().getResponse(), res değerini verir; bu değerin setHeader yöntemi bir başlık ekler.

app.useGlobalInterceptors(...) bir interceptor'ı tüm rotalara uygular; @UseInterceptors(...) ise tek bir denetleyiciye uygular.

challenge icon

Görev

Kolay

“Çalıştır”, src/main.ts dosyasını kullanarak izleyicinizi yeniden başlatır. Ayrı alıştırma dosyaları ağaçta kalabilir; bu sunucu onları başlatmaz.

İstemciler ve kendi izleme sisteminiz, her isteğin ne kadar sürdüğünü bilmek ister. Her başarılı yanıta X-Response-Time yanıt başlığını ekleyin; hiçbir rotaya dokunmayın.

  1. src/common/response-time.interceptor.ts dosyasını açın. ResponseTimeInterceptor içindeki intercept metodunda önce geçerli zamanı Date.now() ile kaydedin. intercept metodunun başındaki kod, rotanın metodu çalışmadan önce çalışır.
  2. context.switchToHttp().getResponse() ile Express'in res nesnesini alın.
  3. next.handle() rotanın metodunu çalıştırır ve sonucunu RxJS observable'ı olarak döndürür: bu, daha sonra gelen bir değerdir. Bu değeri döndürmeye devam edin, ancak zaten rxjs içinden içe aktarılmış olan tap üzerinden, observable'ın .pipe() metodunu kullanarak geçirin. tap'e verdiğiniz işlev, sonuç geldiğinde ve Nest onu göndermeden önce çalışır. Bu işlevde res.setHeader çağrısıyla X-Response-Time değerini, kaydettiğiniz zamandan bu yana geçen milisaniye sayısının sonuna ms ekleyerek ayarlayın; örneğin 3ms. (RxJS'in .pipe() metodu, 3. bölümdeki doğrulama pipe'larıyla ilgili değildir. Observable'a bir adım ekler.)
  4. src/main.ts dosyasında, yanındaki pipe ve filter ile birlikte yeni bir ResponseTimeInterceptor geçirerek tüm uygulama için interceptor'ı app.useGlobalInterceptors(...) ile kaydedin.
  5. Yanıt gövdeleri değişmemelidir. GET /tasks hâlâ { "items": [...], "page": 1, "total": 3, "pages": 2 } döndürür.

Deneyin: GET /tasks gönderin ve yanıtın Headers sekmesini açın. X-Response-Time başlığını, 0ms veya 2ms gibi bir değerle görürsünüz. GET /stats yanıtında da bu başlık bulunur; x-api-key: tasks-key-123 başlığıyla gönderilen { "title": "Buy milk" } gövdeli bir POST isteğinde de bulunur. Ardından bu POST isteğini anahtar olmadan gönderin: yanıt 403 olur ve X-Response-Time başlığı bulunmaz. Nest, guard'ları interceptor'lardan önce çalıştırır; bu nedenle guard, interceptor'ınız başlamadan önce isteği reddetti. Bir rota içinde fırlatılan hata da başlığın eklenmesini engeller; çünkü tap yalnızca bir sonuç geldiğinde çalışır.

Kendin dene

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> {
        // Zamanı kaydedin, handler'ın çalışmasına izin verin, ardından X-Response-Time değerini ayarlayın.
        return next.handle();
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

TypeScript ve NestJS bölümündeki tüm dersler

Kendi başına pratik yap: Express playground