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