未経験からのNestJS入門|インターセプター

概要

NestJS では、インターセプターという概念があります。

インターセプター以下のタイミングで実行されるメソッドを実装できます。

  • クライアントからのリクエストがルーターに渡されるとき
  • ルーターからのレスポンスがクライアントに渡されるとき

インターセプターは、主に以下のような機能を実装するときに使用されます。

  • メソッド実行の前後に追加ロジックのバインドする
  • 関数から返された結果の変換する
  • 関数からスローされた例外を変換する
  • 基本的な機能拡張
  • 特定の条件に応じて関数のオーバーライド

インターセプターを作成するには、@nestjs/common パッケージに存在する NestInterceptor を実装して作成したクラスを使用したいケースに応じて設定するだけです。

インターセプターの実装

自分で一から実装してもいいのですが、Nest CLI を使った方が効率的です。

以下コマンドを叩いてみましょう

nest g in interceptor/logging

インターセプターファイルとインターセプターのテストファイルが作成されます。

インタセプターファイルを実行するときこれだけだと何も処理を設定していないため、動作しているのかわからないです。

そのため、今回はコンソールに文字列を出力するように処理を追加します。

// logging.interceptor.ts

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

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('logger'); ←  追加
    return next.handle();
  }
}

インターセプターファイルを作成しただけでは機能しません。 使用用途に応じて、設定を行わなければいけません。

今回は、users パスにアクセスされた場合にインターセプターを実行をしてみようと思います。

設定方法は簡単で、コントローラーで@nestjs/common パッケージの UserInterceptors デコレータにインターセプターファイルを設定するだけです。

// /users.controllers.ts

import {
Controller,
Get,
Param,
HttpException,
HttpStatus,
ParseIntPipe,
UseInterceptors,
} from '@nestjs/common';
import { ValidationPipe } from '../pipe/validation.pipe';
import { get } from 'http';
import { ForbiddenException } from '../exception/forbidden.exception';
import { LoggingInterceptor } from '../interceptor/logging.interceptor';
import { UsersService } from './users.service';

@UseInterceptors(LoggingInterceptor)  //  追加
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  getUser(): string {
    return this.usersService.getUser();
  }
  @Get(':id')
  getIdUser(@Param('id', ParseIntPipe) id: number): number{
    return id;
  }
  @Get(':id')
  getNameUser(@Param('id', ValidationPipe) id: number): number {
    return id;
  }
  @Get('throw')
  getException(): string {
    throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
  }
  @Get('override')
  getOverRideException(): string {
    throw new HttpException(
    { status: HttpStatus.FORBIDDEN, error: 'override custom' },
      HttpStatus.FORBIDDEN,
    );
  }
  @Get('custom')
  getCustomException(): string {
    throw new ForbiddenException();
  }
}

まとめ

利用用途に応じてカスタムしてみてください。

設定方法によっては全てのアクセスに対してインターセプターを実行することも可能です。