Pipe 是在参数传给 Controller 之前做一些验证和转换的,有 多个内置的 Pipe 可以直接用
Nest 一次请求的顺序是:
Middleware
↓
Guard
↓
Interceptor (before)
↓
Pipe ✅(就在这里)
↓
Controller handler
↓
Interceptor (after)
↓
ExceptionFilter
👉 Pipe 发生在 handler 真正被调用之前,而且是“参数级别”执行
Pipe 的接口定义
export interface PipeTransform<T = any, R = any> {
transform(value: T, metadata: ArgumentMetadata): R;
}
ArgumentMetadata 是关键:
export interface ArgumentMetadata {
type: 'body' | 'query' | 'param' | 'custom';
metatype?: Type<any>;
data?: string;
}
也就是说,Pipe 能知道:
- 这个参数来自哪里(body / query / param)
- DTO 是什么 class
- 装饰器里写的是
@Body('id')还是整个 body
内置的 Pipe 有这些:
- ValidationPipe
- ParseIntPipe
- ParseBoolPipe
- ParseArrayPipe
- ParseUUIDPipe
- DefaultValuePipe
- ParseEnumPipe
- ParseFloatPipe
- ParseFilePipe
看一下使用
nest new pipe-inner -p npm
ParseIntPipe
如果可以转正常展示
如果不可以转 报错
状态码和信息也可以改
可以自己抛一个异常出来,然后让 exception filter 处理
ParseFloatPipe 是把参数转换为 float 类型
也可以 new ParseFloatPipe 的形式,传入 errorHttpStatusCode 和 exceptionFactory
ParseBoolPipe
ParseArrayPipe
需要安装
npm install -D class-validator class-transformer
没有转为数字
指定 item 的类型
这样就把数组每一项处理为 number
ParseEnumPipe
参数不是枚举值内
ParseUUIDPipe
UID 是一种随机生成的几乎不可能重复的字符串,做 id
不是 uuid 会报错
DefaultValuePipe 设置默认值
实现个 Pipe
自己写一个 pipe 也很简单,实现 PipeTransform 接口的 transform 方法,返回值就是传给 handler 的值
nest g pipe aaa --flat --no-spec
生成一个 pipe,打印下参数值,返回 aaa
使用
返回的值是 aaaaaa,也就是说 pipe 的返回值就是传给 handler 的参数值。
打印的 value 就是 query、param 的值,而 metadata 里包含 type、metatype、data