未経験からのNestJS入門|パイプ

概要

NestJS には、渡されたデータをパイプと呼ばれる機能で、検証と変換を行えます。

パイプで想定される使用例は以下の二つです。

  1. 変換
    入力データを目的の形式に変換します(たとえば、文字列から整数に)
  2. 検証
    入力データを評価し、有効な場合は、変更せずに渡します。それ以外の場合は、データが正しくないときに例外をスローします

パイプコントローラルートハンドラと呼ばれる、コントローラーの動的ルートパスにアクセスされたときに呼び出されます。

デフォルトのパイプ

NestJS には、デフォルトでパイプが提供されており、@nestjs/common パッケージからエクスポートすることで使用できます。

デフォルトで用意されいるパイプ以下の 6 つです。

  1. ValidationPipe
  2. ParseIntPipe
    取得したパラメータを文字列から数値に変更します。
    また、数値に変更できない文字列だった場合、例外を出力します。
  3. ParseBoolPipe
  4. ParseArrayPipe
  5. ParseUUIDPipe
  6. DefaultValuePipe

実際に使用方法を見ていきましょう

バインディングパイプ

パイプを使用するには、パイプクラスのインスタンスを適切なコンテキストにバインドし使用します。

今回は ParseIntPipe パイプクラスを例にコードを書いていきます。

未経験からの NestJS 入門|例外』で作成したユーザーコントローラーにそのまま記載してみます。

// /src/users/users.controller.ts

import {
Controller,
Get,
Param,
HttpException,
HttpStatus,
ParseIntPipe,
} from '@nestjs/common';
import { ForbiddenException } from '../exception/forbidden.exception';
import { UsersService } from './users.service';

@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('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();
  }
}

コードの解説

import { Controller, Get, Param, HttpException, HttpStatus, ParseIntPipe } from '@nestjs/common';

パイプを使う前準備として、パラメータ取得用の Param デコレータと、NestJS が提供しているパイプクラス ParsIntPipe をインポートしておきます。

@Get(':id')
getIdUser(@Param('id', ParseIntPipe) id: number): number{
  return id;
}

ルートパスにアクセスされた際に、パラメータ ID を取得するように設定しています。

大事なのは@param メソッドの第二引数にパイプクラス ParseIntPipe を登録していることです。

こうすることで、登録した ParseIntPipe を使用することができます。

カスタムパイプ

Nest.js が提供するデフォルトパイプだけだと、多様な web アプリケーション構築に対応できないかもしれないです。

Nest.js では自分でパイプを作成できるカスタムパイプという機能が存在しています。

Nest CLI でカスタムパイプを作成できるので利用しましょう。

nest g pipe pipe/validation

// /src/pipe/validation.pipe.ts

import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';

@Injectable()
export class ValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
  return value;
}
}

作成されたカスタムパイプはコントローラ側で読み込むだけで使用できます。

先ほど設定した ParseIntPipe の代わりに、ValidationPipe を設定しましょう。

// /src/users/users.controller.ts

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

@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();
  }
}

まとめ

パイプを使用することで、リクエストの数値整形などができて大変便利です。

今回はリクエストされた文字列を数列に変換するだけでしたが、例えばリクエストで渡された日本円をドルに変換するカスタムバリデーションを作ったり、いろいろと応用は聞くかと思います。

今回作成したコードはこちらからダウンロードできます。