怎样用 ValidationPipe 验证 post 请求参数?

30 阅读1分钟

之前 pipe 来对参数做验证和转换,都是 get 请求的参数,如果是 post 请求怎么做?

post 请求的数据是通过 @Body 装饰器来取,并且要有一个 dto class 来接收

(dto 是 data transfer object,数据传输对象,用于封装请求体的数据)

image.png

image.png

image.png

结果

image.png

如果传递 浮点数据 还是可以

image.png

image.png

要对他做参数验证,使用 ValidationPipe

需要

npm install class-validator class-transformer

image.png

image.png

image.png

它属于 Pipe(管道) ,执行时机是:

Middleware
→ Guard
→ Pipe   👈(这里)
→ Interceptor(before)
→ Controller handler
→ Interceptor(after)
→ ExceptionFilter

也就是说:
Controller 方法真正执行之前,ValidationPipe 就已经跑完了

ValidationPipe 源码

export class ValidationPipe implements PipeTransform {
  async transform(value, metadata) {
    const { metatype } = metadata;

    // 1. 是否需要校验
    if (!this.toValidate(metadata)) {
      return value;
    }

    // 2. plain -> class
    const object = plainToInstance(metatype, value);

    // 3. 校验
    const errors = await validate(object);

    if (errors.length > 0) {
      throw new BadRequestException(errors);
    }

    // 4. 返回
    return this.transform ? object : value;
  }
}

pipe 里也是可以注入依赖的

新增 my-validation-pipe.ts

import {
  PipeTransform,
  Injectable,
  ArgumentMetadata,
  BadRequestException,
  Optional,
  Inject,
} from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';

@Injectable()
export class MyValidationPipe implements PipeTransform<any> {
  @Optional()
  @Inject('validation_options')
  private options: any;

  async transform(value: any, { metatype }: ArgumentMetadata) {
    if (!metatype) {
      return value;
    }

    console.log(this.options);
    const object = plainToInstance(metatype, value);
    const errors = await validate(object);
    if (errors.length > 0) {
      throw new BadRequestException('参数验证失败');
    }
    return value;
  }
}


image.png

image.png

可以正常注入

image.png

image.png

没有注入什么依赖,所以这种方式也可以

全局这样写

image.png

class-validator 都支持哪些验证方式

声明这样一个 ppp.dto.ts class

import {
  Contains,
  IsDate,
  IsEmail,
  IsFQDN,
  IsInt,
  Length,
  Max,
  Min,
} from 'class-validator';

export class Ppp {
  @Length(10, 20)
  title: string;

  @Contains('hello')
  text: string;

  @IsInt()
  @Min(0)
  @Max(10)
  rating: number;

  @IsEmail()
  email: string;

  @IsFQDN()
  site: string;
}

使用

image.png

传递正常数据不报错

image.png

image.png

错误消息可修改

image.png

image.png