nestjs开发对前端传递过来的数据进行校验

一、局部验证的方式

  • 1、安装包

    npm i --save class-validator class-transformer
    
  • 2、比如在cat的目录下创建一个dto的文件夹,创建一个create.cat.dto.ts的文件

    import { IsString, IsInt, MinLength, MaxLength } from 'class-validator';
    export class CreateCatDto {
      @IsString({ message: '必须的字符类型' })
      @MinLength(2, {
        message: '长度不能小于2',
      })
      @MaxLength(10, {
        message: '长度不能超过10',
      })
      readonly name: string;
    
      @IsInt({ message: '必须的整数' })
      readonly age: number;
    }
    
  • 3、在cat.controller.ts中使用提交过来的数据约束

    @Controller('cat')
    export class CatController {
      constructor(private readonly catService: CatService) {}
      @Post()
      @HttpCode(HttpStatus.CREATED)
      async create(@Body(new ValidationPipe()) createCatDto: CreateCatDto) {
        Logger.log('-----------创建猫 start--------------');
        Logger.log(createCatDto);
        Logger.log('-----------创建猫 end--------------');
        return '创建猫';
      }
      ...
    }
    

二、全局使用管道校验(前提是先安装包)

  • 1、在根目录下的main.ts文件中

    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    import { Logger, ValidationPipe } from '@nestjs/common';
    import * as helmet from 'helmet';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule, {
        cors: true, // 设置跨站访问
        logger: false,
      });
      // 使用跨站脚本攻击类的库
      app.use(helmet());
      // 给请求添加prefix
      app.setGlobalPrefix('api/v1');
      // 全局使用管道
      app.useGlobalPipes(new ValidationPipe());
      await app.listen(3000, () => {
        Logger.log('服务已经启动,请访问localhost:3000');
      });
    }
    bootstrap();
    
  • 2、在cat.controller.ts中使用提交过来的数据约束

    @Controller('cat')
    export class CatController {
      constructor(private readonly catService: CatService) {}
      @Post()
      @HttpCode(HttpStatus.CREATED)
      async create(@Body() createCatDto: CreateCatDto) { // 这里就不需要使用校验约束
        Logger.log('-----------创建猫 start--------------');
        Logger.log(createCatDto);
        Logger.log('-----------创建猫 end--------------');
        return '创建猫';
      }
      ...
    }
    
  • 3、前端传递数据错误的提示

    {
      "statusCode": 400,
      "error": "Bad Request",
      "message": [
        {
          "target": {
            "name": "哈士奇222",
            "age": "20"
          },
          "value": "20",
          "property": "age",
          "children": [],
          "constraints": {
            "isInt": "必须的整数"
          }
        }
      ]
    }
    

三、约束@Param接受的数据类型

  • 1、安装包

    npm i --save class-validator class-transformer
    
  • 2、直接在cat.controller.ts中使用

    @Controller('cat')
    export class CatController {
      constructor(private readonly catService: CatService) {}
      ...
      @Get(':id')
      @HttpCode(HttpStatus.OK)
      async findOne(
        @Param('id', new ParseIntPipe()) id, // 使用内置的转换整数的管道
        @Query() query: { [propsName: string]: any },
      ) {
        Logger.log('-----------查找一个 start--------------');
        Logger.log(id);
        Logger.log(query);
        Logger.log('-----------查找一个 end--------------');
        return await this.catService.findOne(id);
      }
      ...
    }
    

四、自己创建管道生成验证规则

上面使用的是内置的管道约束,如果没有,我们可以自己创建约束管道

  • 1、在src目录下创建一个文件夹pipe
  • 2、使用命令生成管道

    nest g pi pipe/parseInt
    nest g pi pipe/parseInt --no-spec # 不生成带测试文件的
    
  • 3、书写管道代码

    import {
      ArgumentMetadata,
      Injectable,
      PipeTransform,
      BadRequestException,
    } from '@nestjs/common';
    
    @Injectable()
    export class ParseIntPipe implements PipeTransform<string, number> {
      transform(value: string, metadata: ArgumentMetadata): number {
        const val = parseInt(value, 10);
        if (isNaN(val)) {
          throw new BadRequestException('验证错误');
        }
        return val;
      }
    }
    
  • 4、直接在cat.controller.ts中使用(和内置的一样的使用)

五、自定义返回错误格式

  • 1、命令方式生成自己的校验管道

    nest g pi pipe/Validation --no-spec
    
  • 2、管道的书写

    /*
    * @Description:自定义管道,根据自己格式返回错误信息
    * @Author: 水痕
    * @Github: https://github.com/kuangshp
    * @Email: 332904234@qq.com
    * @Company:
    * @Date: 2019-07-24 14:26:27
    * @LastEditors: 水痕
    * @LastEditTime: 2019-07-24 14:46:45
    */
    import {
      ArgumentMetadata,
      Injectable,
      PipeTransform,
      BadRequestException,
      Logger,
    } from '@nestjs/common';
    import { validate } from 'class-validator';
    import { plainToClass } from 'class-transformer';
    import * as _ from 'lodash';
    
    @Injectable()
    export class ValidationPipe implements PipeTransform<any> {
      async transform(value: any, metadata: ArgumentMetadata) {
        const { metatype } = metadata;
        if (!metatype || !this.toValidate(metatype)) {
          return value;
        }
        const object = plainToClass(metatype, value);
        const errors = await validate(object);
        Logger.log(errors);
        if (errors.length > 0) {
          // 遍历全部的错误信息,返回给前端
          const errorMessage = errors.map(item => {
            return {
              currentValue: item.value,
              [item.property]: _.values(item.constraints)[0],
            };
          });
          throw new BadRequestException(errorMessage);
        }
        return value;
      }
    
      private toValidate(metatype: any): boolean {
        const types = [String, Boolean, Number, Array, Object];
        return !types.includes(metatype);
      }
    }
    
  • 3、使用方式和上面的一样的

  • 4、返回的错误提示

    {
      "data": {
          "error": [
              {
                  "currentValue": "哈士奇21111111111111",
                  "name": "长度不能超过10"
              },
              {
                  "age": "年龄不能为空"
              }
          ]
      },
      "message": "请求失败",
      "code": 1,
      "url": "/api/v1/cat"
      }
    
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水痕01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值