在 NestJS 框架中,Pipe 是一个强大的功能,用于在请求处理程序执行之前验证和转换数据。就是在参数传递到处理函数之前做一些验证和转换处理的 class,NestJS 内置了一系列常用的 Pipe,并且允许开发者根据需求创建自定义 Pipe。下面我们将介绍各种内置 Pipe 的使用例子,并展示如何实现一个自定义 Pipe。
创建自定义Pipe
nest g pipe user
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
@Injectable()
export class UserPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
//这个里面可以修改传入的值以及验证转入值的合法性
return value;
}
}
使用管道
import { Controller,Get,UsePipes,Query} from '@nestjs/common';
import {UserPipe} from '../../user.pipe';
@Controller('user')
export class UserController {
@Get()
index(){
return '用户页面';
}
@Get('pipe')
@UsePipes(new UserPipe())
pipe(@Query() info){
console.log(info);
return `this is Pipe`;
}
}
内置的 Pipe
ValidationPipe、ParseIntPipe、ParseBoolPipe、ParseArrayPipe、ParseUUIDPipe、ParseEnumPipe、ParseFilePipe、ParseFloatPipe、DefaultValuePipe
ValidationPipe
ValidationPipe 用于自动执行输入数据验证。这通常与类类型 (DTO - Data Transfer Objects) 一起使用。一般依赖与两个库来实现class-validator 和 class-transformer.
npm install class-validator class-transformer -S
// 全局管道
app.useGlobalPipes(new ValidationPipe())
ParseIntPipe
在路由中拿参数一般情况下是 string 类型,ParseIntPipe就对拿到的数据进行转换为数字类型,简单的用法就是直接在控制器方法中添加管道
// localhost:3000/user?water=123
@Get()
getHello(@Query('water', ParseIntPipe) water: string): string {
return water;
}
ParseFloatPipe
这个管道是转换为浮点数的,可以使用下看看效果
@Get('water-float')
getFloat(@Query('water', ParseFloatPipe) water: number) {
return water + 2;
}
ParseBoolPipe
通过这个管道把参数值转换为布尔值
@Get('water-bool')
getBool(@Query('water', ParseBoolPipe) water: boolean) {
return water;
}
ParseArrayPipe
这个管道会把传入的参数按照一定的规则解析成数组类型,但是这个依赖class-validator、class-transformer这两个包
@Get('water-arr')
getArr(
@Query(
'water',
new ParseArrayPipe({
items: Number,
}),
)
water: Array<number>,
) {
return water;
}
ParseUUIDPipe
可以转换判断下参数是不是 uuid
@Get('water-uuid')
getUuid(@Query('water', ParseUUIDPipe) water: string) {
return water;
}
ParseEnumPipe
这个管道可以限制传递的参数必须是枚举中的值,如果不是就会报错
enum E {
AAA = '111',
}
@Get('water-enmu')
getEnmu(@Query('water', new ParseEnumPipe(E)) water: E) {
return water;
}
DefaultValuePipe
这个管道可以用来设置默认值,如果没有没有传递任何参数那么就用默认值
@Get('water-df')
getDf(@Query('water', new DefaultValuePipe('water')) water: string) {
return water;
}
Nestjs中管道结合Joi库实现数据验证
npm install --save @hapi/joi
npm install --save-dev @types/hapi__joi
import { ArgumentMetadata, Injectable, PipeTransform, BadRequestException } from '@nestjs/common';
import * as Joi from '@hapi/joi';
@Injectable()
export class InfoPipe implements PipeTransform {
constructor(private readonly schema) { }
async transform(value: any, metadata: ArgumentMetadata) {
console.log(value);
const { error } = Joi.validate(value, this.schema)
if (error) {
throw new BadRequestException('发送语义有误')
}
return value;
}
}
import * as Joi from '@hapi/joi';
let rootInfo = Joi.object().keys({
name: Joi.string().required(),
age: Joi.number().integer().min(6).max(66).required(),
})
@Get()
@UsePipes(new InfoPipe(rootInfo))
root(@Query() info) {
return `hello world`;
}
class-validator和class-transformer的使用
xxxx.dto.ts文件中添加验证, 完善错误信息提示
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
export class CreatePostDto {
@ApiProperty({ description: '文章标题' })
@IsNotEmpty({ message: '文章标题必填' })
readonly title: string;
@IsNotEmpty({ message: '缺少作者信息' })
@ApiProperty({ description: '作者' })
readonly author: string;
@ApiPropertyOptional({ description: '内容' })
readonly content: string;
@ApiPropertyOptional({ description: '文章封面' })
readonly cover_url: string;
@IsNumber()
@ApiProperty({ description: '文章类型' })
readonly type: number;
}
在路由中配置DTO对象
@controller()
class etesxcontroller{
@post()
hello(@body(new testpipe()) post:CreatePostDto){}
//testpipe 入参value就是dto可以修改dto的value
}
在main.ts中全局注册一下管道ValidationPipe
app.useGlobalPipes(new ValidationPipe());