前言
在开始本节内容之前,如果还没有从全面视角了解过
Nest
请求流程,建议先看【Nest全栈之旅】第三章:理解Nest请求流程,连贯你的知识点,它介绍了请求过程中会经过的必要环节,回来看这篇文章效果更佳。
管道是运行在由控制器路由处理器
处理的 arguments
上,Nest
会在调用每一个方法之前插入Pipe
,由Pipe
对传入的参数进行处理操作,之后再交给路由处理程序。
内置管道
Nest
中提供了9种开箱即用的内置管道供我们直接使用:
- ValidationPipe
- ParseIntPipe
- ParseFloatPipe
- ParseBoolPipe
- ParseArrayPipe
- ParseUUIDPipe
- ParseEnumPipe
- DefaultValuePipe
- ParseFilePipe
他们都实现了PipeTransform
接口规范和transform
方法,来看看ParseFloatPipe
方法定义源码:

我们拿几个运行一下。
1、ParseIntPipe

前端通过简单的React
项目发送个请求,传递一个非Number
类型的参数

不出意外,管道验证器会校验失败,返回400
,期望是数值类型

当然,我们可以修改这个返回异常信息,从源码中可以看到支持修改status
和传入一个异常处理
工厂函数。

来试一下,修改状态码为500
,并且定义一个函数返回HttpException
给到全局自定义过滤器统一捕获

这里是自定义的全局异常过滤器,专门捕获Http
异常
最后返回统一异常信息
接下来再试试其他Pipe
2、ParseBoolPipe
将参数转化为boolean
类型

给参数设置Pipe
转换
Nest
中可以拿到对应的flag
参数

3、ParseUUIDPipe
这个Pipe
是用来验证传递的参数是不是uuid
,而这个uuid
几乎是不可能重复的,所以如果传递一个非uuid
的参数,就会报错,常见的场景是一些需要加密的地方,比如登录密码、登录token信息等。
来试一下,前端传递一个uuid
过来
通过
get
方式获取
依然可以正确校验并返回
其他类似,但一些可能需要引入class-validator
和class-transform
两个库进行验证,比如ParseArrayPipe
依赖ValidationPipe
,而ValidationPipe
需要依赖上面两个验证库。
自定义管道
看了内置管道之后,如果还不能满足要求,当然我们可以进行自定义。 前面说了,自定义管道需要实现PipeTranform
类下的transform
方法,我们一起来看一下

上面实现了自己的ParseIntPipe
类,与内置Pipe
不同的是,这里是将参数转为8进制,实现了特殊的管道需求。
我们来试一下,引入自定义管道


前端参数传递10

可以看到Nest
中已经转化为了8
进制的值
通过这种方式就可以自由发挥自定义能力啦!
DTO模式
上面展示了是Get
请求携带比较简单的参数验证和转换,那如果是Post
请求携带了大量数据过来呢,不可能一个个使用内置管道进行校验吧?效率太低了吧
这时候就要用到前面说的两个验证库了:class-validator
和class-transform
。
声明一个专门用来验证参数的DTO
class类

同样的,我们在Controller
的Post
方法中引入这个类

并且注册全局的管道验证器
当然如果不想全局注册,就需要在每个方法上定义,像这样

接着在前端发起一个Post
请求create-person
接口

请求参数中sex
写为错误的Number
类型

来看看效果,返回sex
类型错误异常
我们把它改为string
类型再试试
可以看到
Nest
中拿到了正确的Body
参数
总结
Pipe
是作为参数类型验证的必经之路,官方有内置的9种Pipe
可以直接使用,上面简单演示了几种方法,同时也了解了实现自定义Pipe
必须实现PipeTransform
接口的transform
方法,它的返回值会传给路由处理程序。
根据不同的业务场景,我们也可以自定义自己的管道验证器来满足不同的需求。
最后,作为Post
请求方式,介绍了DTO
验证模式,可以很好管理参数验证,并且为不同的参数返回指定的错误,这对于前端来说是非常友好的事情。