• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

神光《Nest 通关秘籍》学习-9种常见的Pipe参数校验方式

武飞扬头像
白哥学前端
帮助4

最近在学习神光大神的《Nest通关秘籍》,该小册主要包含下面这些内容:

学新通 想购买的可以点击《传送门》。

接下来的日子里,我将更新一系列的学习笔记。感兴趣的可以关注我的专栏《Nest 通关秘籍》学习总结

特别申明:本系列文章已经经过作者本人的允许。 大家也不要想着白嫖,我的笔记只是个人边学习边记录的,不是很完整,大家想要深入学习还是要自己去购买原版小册。

本章我们来学习如何通过nest中的Pipe来对参数进行校验。

学新通

Pipe 是在参数传给 handler 之前对参数做一些验证和转换的 class。

内置的 Pipe 有这些:

  • ValidationPipe
  • ParseIntPipe
  • ParseBoolPipe
  • ParseArrayPipe
  • ParseUUIDPipe
  • DefaultValuePipe
  • ParseEnumPipe
  • ParseFloatPipe
  • ParseFilePipe

它们都实现了 PipeTransform 接口:

1. ParseIntPipe

import { Controller, Get, ParseIntPipe, Query } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(@Query('a', ParseIntPipe) aa): string {
    return aa   1;
  }
}

当我们传入的参数是int类型的时候,会正常返回,如果不是,会报错:

学新通

这里我们还可以指定错误状态码:

import {
  Controller,
  Get,
  HttpStatus,
  ParseIntPipe,
  Query,
} from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(
    @Query(
      'a',
      new ParseIntPipe({
        errorHttpStatusCode: HttpStatus.NOT_FOUND,
      }),
    )
    a,
  ): string {
    return a   1;
  }
}

注意:需要new ParseIntPipe()

返回的错误码就会变成404了。

还可以抛一个异常出来,然后让 exception filter 处理:

import {
  Controller,
  Get,
  HttpException,
  HttpStatus,
  ParseIntPipe,
  Query,
} from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(
    @Query(
      'a',
      new ParseIntPipe({
        exceptionFactory: (msg) => {
          console.log(msg);
          throw new HttpException('xxx'   msg, HttpStatus.NOT_FOUND);
        },
      }),
    )
    a,
  ): string {
    return a   1;
  }
}

可以看到,状态码和 message 都改了:

学新通

也可以加个 @UseFilters 来使用自己的 exception filter 处理.

2. ParseFloatPipe

@Get('b')
getB(
  @Query('b', new ParseFloatPipe())
  a,
): string {
  return a   1;
}

学新通

3. ParseBoolPipe

@Get('c')
getC(
  @Query('a', new ParseBoolPipe())
  a,
): string {
  return typeof a;
}

学新通

4. ParseArrayPipe

安装两个包:

pnpm install -D class-validator class-transformer
  • class-validator:用装饰器和非装饰器两种方式对 class 属性做验证的库
  • class-transformer:把普通对象转换为对应的 class 实例的包
@Get('d')
getD(
  @Query('a', new ParseArrayPipe({}))
  a: Array<number>,
) {
  return a.reduce((total, item) => total   item, 0);
}

学新通

发现它并没有转化成Number类型,所以返回了0123

这时候就需要用 new XxxPipe 的方式传入参数了:

@Get('d')
getD(
  @Query(
    'a',
    new ParseArrayPipe({
      items: Number,
    }),
  )
  a: Array<number>,
) {
  return a.reduce((total, item) => total   item, 0);
}

这时候就能得到正确的结果了:

学新通此外,你还可以指定分隔符:

@Get('f')
getF(
  @Query(
    'a',
    new ParseArrayPipe({
      separator: '..',
    }),
  )
  a: Array<string>,
) {
  return a;
}

学新通

如果不传参的时候会报错,可以设置为optional

@Get('f')
getF(
  @Query(
    'a',
    new ParseArrayPipe({
      separator: '..',
      optional: true,
    }),
  )
  a: Array<string>,
) {
  return a;
}

5. ParseEnumPipe

ParseEnumPipe的使用场景是这样的:

限制参数的取值范围

先定义一个路径的枚举类型:

enum PATHENUM {
  AAA = '111',
  BBB = '222',
  CCC = '333',
}
@Get('g/:enum')
getG(
  @Param('enum', new ParseEnumPipe(PATHENUM))
  e: PATHENUM,
) {
  return e;
}

当我们访问PATHENUM中的值的时候正常返回,如果我们访问一个http://127.0.0.1:3000/g/444,就会报下面的错误:

学新通

6. ParseUUIDPipe

UUID 是一种随机生成的几乎不可能重复的字符串,可以用来做 id。

我们先来生成一个UUID

// eslint-disable-next-line @typescript-eslint/no-var-requires
const uuid = require('uuid');

console.log(uuid.v4());

这样会生成一个v4的uuid

学新通

然后我们使用ParseUUIDPipe来校验一下:

@Get('h/:uuid')
getH(
  @Param('uuid', new ParseUUIDPipe())
  uuid: string,
) {
  return uuid;
}

学新通

如果是错误的UUID,会报错:

学新通

7. DefaultValuePipe

这个是设置参数默认值的,当你没传参数的时候,会使用默认值:

@Get('i')
getI(
  @Query('iii', new DefaultValuePipe('123'))
  iii: string,
) {
  return iii;
}

无参数:

学新通

有参数:

学新通

以上都是Get参数。如果用POST参数,阁下应该如何应对?

8. ValidationPipe

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

export class CreateAaaDto {
  name: string;
}
import {
  Controller,
  Post,
} from '@nestjs/common';
import { AaaService } from './aaa.service';
import { CreateAaaDto } from './dto/create-aaa.dto';

@Controller('aaa')
export class AaaController {
  constructor(private readonly aaaService: AaaService) {}

  @Post()
  create(@Body() createAaaDto: CreateAaaDto) {
    console.log(createAaaDto);
  }
}

学新通

学新通

可以看到正常接收到了参数。当我们在Body中接受的参数类型各种各样的时候,就需要对这些参数进行验证,也就是Validationpipe

它需要依赖下面两个包:

pnpm install -D class-validator class-transformer

然后在 @Body 里添加这个Validationpipe

import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  ValidationPipe,
} from '@nestjs/common';
import { AaaService } from './aaa.service';
import { CreateAaaDto } from './dto/create-aaa.dto';

@Controller('aaa')
export class AaaController {
  constructor(private readonly aaaService: AaaService) {}

  @Post()
  create(@Body(new ValidationPipe()) createAaaDto: CreateAaaDto) {
    console.log(createAaaDto);
  }
}

在 dto 这里,用 class-validator 包的 @IsInt 装饰器标记一下:

import { IsInt } from 'class-validator';
export class CreateAaaDto {
  name: string;
  @IsInt()
  age: number;
}

现在当我们把age的参数传成非number类型的,就会报错了:

学新通

如果传成正确的类型,就会正常返回了:

学新通

学新通

class-validator 都支持的验证方式:

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;
}

大家可以自己去一个一个地验证。

9. ParseFilePipe

未完待续。。。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhcafibc
系列文章
更多 icon
同类精品
更多 icon
继续加载