インターセプター
CoddyのNode.jsジャーニー「TypeScriptとNestJS」セクションの一部。レッスン 16/17。
各ハンドラーに手を加えずに、すべての応答に処理時間を含めたいとします。インターセプターはハンドラーをラップします。next.handle()より前のコードはハンドラーの実行前に動き、next.handle()が返すものに対するコードは実行後に動きます。
intercept(context: ExecutionContext, next: CallHandler) {
console.log('before');
return next.handle().pipe(
tap(() => console.log('after')),
);
}next.handle()は、後から値が届くRxJSのオブザーバブルとして、ハンドラーの結果を返します。pipe(tap(...))は、その値が届いたとき、Nestがそれを送信する前に関数を実行します。パイプ処理したオブザーバブルを返してください。Nestはその中身を送信します。context.switchToHttp().getResponse()はresを返し、そのsetHeaderでヘッダーを追加できます。
app.useGlobalInterceptors(...)はすべてのルートにインターセプターを適用し、@UseInterceptors(...)は1つのコントローラーに適用します。
チャレンジ
簡単ResponseTimeInterceptorを完成させましょう。すべての応答に、ハンドラーの処理時間をミリ秒で示すX-Response-Timeを含めます。たとえば3msのようになります。- アプリ全体に登録します。
GET /tasksとGET /statsを送信してHeadersタブを開き、その後、キーを指定せずにPOST /tasksを送信します。
自分で試してみよう
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> {
// 時刻を記録し、ハンドラーを実行してから、X-Response-Time を設定します。
return next.handle();
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。