NestJS で ストロングパラメータ- みたいなことをしたい
背景
DTOでValidationを実装したはいいけど、DTOで定義していないパラメータを除外したい。
Railsのストロングパラメーター の permit にあたる機能を NestJS で探していたのですが、名称が違うのでここで紐付けておきます。
環境
- @nestjs/core (v8.0.0)
やりたいこと
Railsのストロングパラメーター の permit を NestJS でも実装したい。
例えば、以下のようなリクエストを行ったとします。
// POST localhost:3000
{
"id": "1",
"age": 29,
"name": "bob"
}
上記リクエストのBodyから受け取りたいパラメータを validation しつつ、validation を通過したパラメータだけサーバーサイド側で受け取り、それ以外は除外したい。
上記でvalidationを行うパラメータはid,ageだけの場合、以下のようになるイメージです。
※ Railsでいうと下記のような設定になるはずです。
params.permit(:id, :age)
すると、paramsから取得できるパラメーターは以下のようになるはずです。
// POST localhost:3000
{
"id": "1",
"age": 29,
}
nameは許可(permit)されていないので除外されています。
なぜストロングパラメータを使いたいのか
-
validationを通過していないパラメータを除外したい - フロントエンドでのパラメーター選別作業が面倒なため
サーバーサイド側でvalidationついでに必要ないパラメーターを除外したほうが、セキュリティ的にも安全で、フロントエンドでリクエスト時にパラメーターを選別が不要になり一石二鳥です🐔
Railsでは実装方法がRailsチュートリアルなどで、ストロングパラメータを扱うので一般的ですが、NestJSの場合どうするのかすぐ出てきませんでした。
ドキュメントを漁ると、NestJSの場合、validationとパラメーターの除外はDTOというファイルと、whitelistをtrueにすることで実装することができました。
Railsのストロングパラメーターのpermitは、NestJSではstripping-propertiesと呼ばれているのですね。
whitelist を true に設定
グローバルに設定したい場合は下記のように, bootstrap上で定義します。
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
+ app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
await app.listen(3000);
}
bootstrap();
個別にメソッド単位で定義する場合は、controllerやresolver単位で設定できます。
import { Body, Controller, Get, Param, Post, Query, UsePipes, ValidationPipe } from '@nestjs/common';
import { GreetingDto } from './greeting-dto';
@Controller()
export class AppController {
@Post()
+ @UsePipes(new ValidationPipe({ whitelist: true }))
getGreeting(@Body() greeting: GreetingDto) {
return greeting;
}
}
注意
whitelistを使用するときは、class-validatorとclass-transformerをinstallする必要があります。まだ追加されていないプロジェクトであれば追加してください。
npm i class-validator class-transformer
POSTの場合
さきほど、idとageをvalidationを行うDTOファイルを作成しvalidationを行います。
import { Transform } from 'class-transformer';
import { IsNumber, IsNumberString, IsOptional } from 'class-validator';
export class GreetingDto {
@IsNumberString()
id: string;
@IsNumber()
age: number;
}
上記のDTOファイルをgetGreetingの型に使用すると、NestJSがvalidationを行う設定ができました。
import { Body, Controller, Get, Param, Post, Query, UsePipes, ValidationPipe } from '@nestjs/common';
import { GreetingDto } from './greeting-dto';
@Controller()
export class AppController {
@Post()
@UsePipes(new ValidationPipe({ whitelist: true }))
getGreeting(@Body() greeting: GreetingDto) {
return greeting;
}
}
whitelist が false(デフォルト) のとき
POST localhost:3000
{
"id": "1",
"age": 29,
"name": "bob"
}
{
"id": "1",
"age": 29,
"name": "bob"
}
whitelist が true のとき
POST localhost:3000
{
"id": "1",
"age": 29,
"name": "bob"
}
{
"id": "1",
"age": 29
}
ちゃんと、DTOで定義されていないパラメータは除外されました。
Discussion