[NestJS] NestJs Data Validation with ValidationPipe

For example we have a rest endpoint, we need to validate the data we receive in correct format:

import { IsMongoId, IsString, IsBoolean, IsInt } from "class-validator";

export class Course {
  @IsString()
  @IsMongoId()
  _id: string;

  @IsInt({ message: "seqNo must be numeric" })
  seqNo: number;
  // always false, no need to be always applied the rule
  @IsString({ always: false }) url: string;
  @IsString() iconUrl: string;
  @IsString() courseListIcon: string;
  @IsString() description: string;
  @IsString() longDescription: string;
  @IsString() category: string;
  @IsInt() lessonsCount: number;
  @IsBoolean() promo: boolean;
}

 

 

We can use ValidationPipe to ensure all the endpoint receive the correct data:

import {
  Controller,
  Get,
  Param,
  Put,
  Body,
  Delete,
  Post,
  BadRequestException,
  UseFilters,
} from '@nestjs/common';
import { Course } from '../../../../shared/course';
import { CoursesRepository } from '../repositories/courses.repository';

@Controller('courses')
export class CoursesController {
  constructor(private couresDB: CoursesRepository) {}

  @Post()
  async createCourse(@Body() course: Course): Promise<Course> {
    return this.couresDB.addCourse(course);
  }
... }

 

Use global filter:

import { BadRequestException } from '@nestjs/common';

export class ValidationException extends BadRequestException {
  constructor(public validationErrors: string[]) {
    super();
  }
}

----
import { Catch, ExceptionFilter, ArgumentsHost }
from '@nestjs/common'; import { ValidationException } from './validation.exception'; @Catch(ValidationException) export class ValidationFilter implements ExceptionFilter { catch(exception: any, host: ArgumentsHost): any { const ctx = host.switchToHttp(), response = ctx.getResponse(); return response.status(400).json({ statusCode: 400, createdBy: 'ValidationFilter', validationErrors: exception.validationErrors, }); } }

 

main.ts:

import { NestFactory } from '@nestjs/core';

import { AppModule } from './app.module';
import { HttpExceptionFilter } from './filters/http-exception.filter';
import { FallbackExpectionFilter } from './filters/fallback.filter';

import * as mongoose from 'mongoose';
import { ValidationPipe, ValidationError } from '@nestjs/common';
import { ValidationFilter } from './filters/validation.filter';
import { ValidationException } from './filters/validation.exception';

mongoose.set('useFindAndModify', false);

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.setGlobalPrefix('api');
  // order matters
  app.useGlobalFilters(
    new FallbackExpectionFilter(),
    new HttpExceptionFilter(),
    new ValidationFilter(),
  );
  app.useGlobalPipes(
    new ValidationPipe({
      skipMissingProperties: true,
      // trigger when validation error occur
      exceptionFactory: (errors: ValidationError[]) => {
        const message = errors.map(
          error =>
            `${error.property} has wrong value ${error.value}, ${Object.values(
              error.constraints,
            ).join(', ')}`,
        );

        return new ValidationException(message);
      },
    }),
  );

  await app.listen(9000);
}

bootstrap();

 

posted @ 2020-02-04 14:57  Zhentiw  阅读(1306)  评论(0编辑  收藏  举报