Menu
CoddyTech

Interceptor

Termasuk bagian TypeScript dan NestJS dalam perjalanan Node.js di Coddy. Pelajaran 23 dari 24.

Kamu ingin setiap jawaban menyebutkan berapa lama waktu yang dibutuhkan, tanpa mengubah setiap handler. interceptor membungkus handler: kode sebelum next.handle() berjalan sebelumnya, dan kode pada hasil yang dikembalikan next.handle() berjalan sesudahnya.

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

next.handle() memberikan hasil handler sebagai observable RxJS, yaitu nilai yang tiba kemudian. .pipe(tap(...)) menjalankan fungsi saat nilainya tiba, sebelum Nest mengirimkannya; pipe ini tidak ada hubungannya dengan pipe validasi Nest. Guard berjalan sebelum interceptor mana pun, jadi permintaan yang ditolak oleh guard tidak pernah mencapainya. Kembalikan observable yang telah diproses oleh pipe: Nest mengirimkan nilai yang dibawanya. context.switchToHttp().getResponse() memberikan res, yang setHeader-nya menambahkan header.

app.useGlobalInterceptors(...) menerapkan interceptor ke setiap route; @UseInterceptors(...) menerapkannya ke satu controller.

challenge icon

Tantangan

Mudah

Jalankan memulai tracker-mu lagi, menggunakan src/main.ts. File latihan yang terpisah bisa tetap ada di pohon direktori, server ini tidak menjalankannya.

Client dan sistem pemantauanmu sendiri ingin mengetahui berapa lama setiap permintaan berlangsung. Tambahkan header respons, X-Response-Time, ke setiap respons yang berhasil, tanpa mengubah rute mana pun.

  1. Buka src/common/response-time.interceptor.ts. Di dalam metode intercept milik ResponseTimeInterceptor, catat waktu saat ini terlebih dahulu menggunakan Date.now(). Kode di bagian atas intercept dijalankan sebelum metode rute.
  2. Dapatkan res milik Express dengan context.switchToHttp().getResponse().
  3. next.handle() menjalankan metode rute dan mengembalikan hasilnya sebagai observable RxJS: nilai yang tiba belakangan. Tetap kembalikan hasilnya, tetapi teruskan melalui tap, yang sudah diimpor dari rxjs, menggunakan metode .pipe() milik observable. Fungsi yang kamu berikan kepada tap dijalankan saat hasilnya tiba, sebelum Nest mengirimkannya. Di dalam fungsi itu, panggil res.setHeader untuk mengatur X-Response-Time ke jumlah milidetik sejak kamu mencatat waktu, diikuti ms, seperti 3ms. (.pipe() milik RxJS tidak ada hubungannya dengan pipe validasi di bab 3. Metode ini menambahkan satu langkah ke observable.)
  4. Di src/main.ts, daftarkan interceptor untuk seluruh aplikasi dengan app.useGlobalInterceptors(...), berikan instance baru ResponseTimeInterceptor, di samping pipe dan filter.
  5. Isi respons tidak boleh berubah. GET /tasks tetap mengembalikan { "items": [...], "page": 1, "total": 3, "pages": 2 }.

Coba: kirim GET /tasks dan buka tab Headers pada respons. Kamu akan melihat X-Response-Time dengan nilai seperti 0ms atau 2ms. GET /stats juga memilikinya, begitu pula POST dengan { "title": "Buy milk" } yang dikirim bersama header x-api-key: tasks-key-123. Lalu kirim POST itu tanpa kunci: 403, dan tidak ada X-Response-Time. Nest menjalankan guard sebelum interceptor, jadi guard menolak permintaan sebelum interceptor-mu mulai bekerja. Error yang dilemparkan di dalam rute juga membuat header tidak disertakan, karena tap hanya dijalankan saat hasil tiba.

Coba sendiri

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> {
        // Catat waktunya, biarkan handler berjalan, lalu atur X-Response-Time.
        return next.handle();
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di TypeScript dan NestJS

Latihan sendiri: Playground Express