Poznałeś strażników (dekoratory class-validator) i wiesz, jak opisać reguły walidacji w DTO. Ale kto tak naprawdę uruchamia tych strażników? Odpowiedzią jest ValidationPipe — to jak główny oficer kontrolny stojący przy bramie i koordynujący pracę wszystkich strażników.
ValidationPipe to wbudowany pipe NestJS, który automatycznie:
Najwygodniejszy sposób to włączenie ValidationPipe globalnie dla całej aplikacji:
1// main.ts - Brama Główna Imperium
2import { NestFactory } from '@nestjs/core';
3import { ValidationPipe } from '@nestjs/common';
4import { AppModule } from './app.module';
5
6async function bootstrap() {
7 const app = await NestFactory.create(AppModule);
8
9 // Ustawienie globalnej straży na bramie
10 app.useGlobalPipes(new ValidationPipe());
11
12 await app.listen(3000);
13}
14bootstrap();ValidationPipe przyjmuje obiekt opcji, który pozwala dostosować zachowanie straży:
1app.useGlobalPipes(new ValidationPipe({
2 whitelist: true,
3}));Z opcją
whitelist: true pipe automatycznie usunie wszystkie pola, które nie mają dekoratorów walidacji w DTO. To jak strażnik, który zabiera podejrzane przedmioty na bramie:1// DTO pozwala tylko na 'name' i 'age'
2export class CreateLegionaryDto {
3 @IsString()
4 name: string;
5
6 @IsNumber()
7 age: number;
8}
9
10// Przychodzi request z dodatkowym polem:
11// { name: "Marcus", age: 25, isAdmin: true }
12
13// Z whitelist: true, pole 'isAdmin' zostaje usunięte
14// Kontroler dostaje: { name: "Marcus", age: 25 }1app.useGlobalPipes(new ValidationPipe({
2 whitelist: true,
3 forbidNonWhitelisted: true,
4}));To jeszcze surowsza opcja — zamiast usuwać nieznane pola, serwer zwraca błąd. Strażnik nie zabiera przedmiotów, ale od razu odmawia wejścia:
1// { name: "Marcus", age: 25, isAdmin: true }
2// Odpowiedź: 400 Bad Request
3// "property isAdmin should not exist"1app.useGlobalPipes(new ValidationPipe({
2 transform: true,
3}));Parametry URL zawsze przychodzą jako stringi. Z opcją
transform: true pipe automatycznie konwertuje je na odpowiednie typy:1@Get(':id')
2findOne(@Param('id') id: number) {
3 // Bez transform: id jest stringiem "42"
4 // Z transform: id jest liczbą 42
5 console.log(typeof id); // "number"
6}Możesz też użyć ValidationPipe na konkretnym endpoincie zamiast globalnie:
1@Post()
2@UsePipes(new ValidationPipe({ whitelist: true }))
3createLegionary(@Body() dto: CreateLegionaryDto) {
4 return this.service.create(dto);
5}Albo na konkretnym parametrze:
1@Post()
2createLegionary(
3 @Body(new ValidationPipe({ whitelist: true })) dto: CreateLegionaryDto,
4) {
5 return this.service.create(dto);
6}Oto konfiguracja, którą stosuje większość projektów NestJS:
1app.useGlobalPipes(new ValidationPipe({
2 whitelist: true,
3 forbidNonWhitelisted: true,
4 transform: true,
5 transformOptions: {
6 enableImplicitConversion: true,
7 },
8}));Ta konfiguracja zapewnia:
whitelist)forbidNonWhitelisted)transform)enableImplicitConversion)ValidationPipe to fundament bezpieczeństwa twojego API. Bez niego dekoratory class-validator są jak strażnicy bez dowódcy — nie wiedzą kiedy działać!