一般在控制器中引入使用,作用有两个 -
类型转换:将输入数据转换为所需的类型(例如,从字符串转到整数)
数据校验:校验输入数据,如果有效的,则简单地通过它;否则,当数据不正确时抛出异常
在这两种情况下,管道都对控制器路由处理程序处理的参数进行操作。 Nest 在调用方法之前插入一个管道,管道接收指定给该方法的参数并对它们进行操作。任何转换或验证操作都会在此时发生,之后会使用任何(可能)转换的参数调用路由处理程序。
nest 内置的管道类有:
通过 @nestjs/common 包引入
ValidationPipe ParseIntPipe ParseFloatPipe ParseBoolPipe ParseArrayPipe ParseUUIDPipe ParseEnumPipe DefaultValuePipe ParseFilePipe
// user.controller.ts
import {Controller, Get, Param, ParseIntPipe} from '@nestjs/common';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {
}
@Get('/:id')
test(@Param('id', ParseIntPipe) id: number) {
console.log(typeof id); // number 类型
return 'test';
}
}还可以传入异常处理参数
@Get('/:id')
test(@Param('id', new ParseIntPipe({errorHttpStatusCode:HttpStatus.NOT_ACCEPTABLE})) id: number) {
console.log(typeof id);
return 'test';
}这样如果输入数据错误,nest 会直接抛出异常以及错误代号,可以考虑通过Exception filters 捕获异常
{
"statusCode": 406,
"message": "Validation failed (numeric string is expected)",
"error": "Not Acceptable"
}使用UsePipes引入管道:
@Get('/:id')
@UsePipes(new ParseIntPipe({errorHttpStatusCode:HttpStatus.NOT_ACCEPTABLE})) //效果一样
test(@Param('id') id: number) {
console.log(typeof id);
return 'test';
}第一步: 安装依赖
$ npm i --save class-validator class-transformer
第二步:定义数据类型Dto
//person.dto.ts
import {IsString, IsInt} from 'class-validator';
import {Transform} from "class-transformer";
export class Person {
@IsString()
name: string;
@IsInt()
@Transform(value => parseInt(value.value)) //自动类型转换将“age”自动转换为数字类型
age: number;
}第三步:引入校验
// user.controller.ts
import {Controller, Get, Post, Query, UsePipes, ValidationPipe} from '@nestjs/common';
import {UserService} from './user.service';
import {Person} from "./Dto/person.dto";
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {
}
@Get('/')
index(@Query(new ValidationPipe({transform:true})) query: Person) {
return this.userService.index(query);
}
// 或者使用UsePipes装饰器引入
@Get('/')
@UsePipes(new ValidationPipe({transform: true}))
index(@Query() query: Person) {
return this.userService.index(query);
}
}注意:这里传入transform: true 参数是因为在dto中需要将age类型从string自动转换为 数字类型,如果校验中不需要数据类型转换,则不需要传入此参数。
ValidationPipe 可以传入的参数有
export interface ValidationPipeOptions extends ValidatorOptions {
transform?: boolean; // 是否开启类型转换
disableErrorMessages?: boolean; // 是否禁用详细错误
exceptionFactory?: (errors: ValidationError[]) => any;}
}除了上述验证,如果输入的数据是类class,也可以通过第三方Joi进行验证。
第一步:安装依赖
$ npm install --save joi
第二步:定义类模型和Dto
// animal.dto.ts
import * as Joi from "joi";
export const AnimalSchema = Joi.object({
sex: Joi.string().required(),
age: Joi.number()
.min(3)
.max(10)
.required(),
});
export class Animal {
sex: string;
age: number;
}第三步:自定义validation 管道逻辑
//joi.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import { ObjectSchema } from 'joi';
@Injectable()
export class JoiValidationPipe implements PipeTransform {
constructor(private schema: ObjectSchema) {}
transform(value: any, metadata: ArgumentMetadata) {
const { error } = this.schema.validate(value);
if (error) {
throw new BadRequestException('Validation failed');
}
return value;
}
}第四步:引入管道到控制器
// user.controller.ts
import {Animal, AnimalSchema} from "./Dto/animal";
import {JoiValidationPipe} from "./validation.pipe";
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {
}
@Get('/animal')
@UsePipes(new JoiValidationPipe(AnimalSchema))
animal(@Query() query: Animal) {
console.log(query);
return 'animal';
}
}如果请求输入数据不合法,同样会抛出400 BadRequest 异常
// parse-int.pipe.ts
import { PipeTransform, Injectable, ArgumentMetadata, 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('Validation failed');
}
return val;
}}方法一:在main.ts app下引入
//main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);}bootstrap();
}方法二:模块中引入:
// app.module.ts
import { Module } from '@nestjs/common';
import { APP_PIPE } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_PIPE,
useClass: ValidationPipe,
},
],
})
export class AppModule {}www.haizhuan.tk