D4 训练的是继续理解 Nest.js 框架的核心部件,管道(Pipes)还有守卫(Guards)。管道的两个主要的作用是转换与验证数据。 守卫决定了是否让请求通过。
管道
管道(Pipes),在 Nest.js 框架里,这种东西有两个主要的作用,一个是转换数据,一个是验证数据。框架里自带了两个管道,ValidationPipe 可以用来验证数据,ParseIntPipe,它可以把字符串转换成数字类型的值。
下面是一个请求处理器方法,里面用 @Body 装饰器装饰了一下 post 这个参数,这样 post 参数里的值就会是请求里的主体数据。
store(@Body() post: CreatePostDto) {}
这个数据我们设置了一个类型是 CreatePostDto,在这个类型里规定了请求主体里可能包含的数据还有对应的类型:
export class CreatePostDto { readonly title: string; readonly body: string; }
CreatePostDto 这个类型可以定义成一个类,里面添加一些属性,然后设置一下这些属性的值的类型是什么。不过现在的问题是,请求那里发送的数据,数据的类型与这些属性的值的类型不匹配,也不会发生什么。我们可以使用数据验证管道去验证它们。
要使用这个验证功能还得再去安装两个包,一个是 class-transformer,还有一个是 class-validator。
先在这个类型里使用 class-validator 这个包里的一些装饰器去设置一下验证的规则,像这样:
import { IsString } from 'class-validator'; export class CreatePostDto { @IsString() readonly title: string; @IsString() readonly body: string; }
上面从 class-validator 里面解构出来了 IsString,用这个装饰器装饰了一下这个类里的两个属性,它的作用就是设置了验证的规则是字符串。
现在就可以绑定使用验证数据用的管道了:
import { UsePipes, ValidationPipe } from '@nestjs/common'; @UsePipes(ValidationDemoPipe) store(@Body() post: CreatePostDto) {}
绑定管道用的就是 @UsePipes 这个装饰器,把要绑定使用的管道交给它就可以了。现在如果在客户端那里发过来的请求里带的数据的类型不符合我们设置的规则,应用就会报异常提醒客户端要使用正确类型的数据。
守卫
守卫(Guards),它的主要使用检查过来的请求,然后根据一些条件,再决定是否放行这个请求,放行的话,就是让这个请求接触到它的处理器(控制器里的一个方法),如果不放行,应用会响应回一个异常,提示客户端到底哪里出了问题,比如可能是因为请求没有通过身份验证,或者请求的用户不满足某些条件,比如用户没有特定的用户角色等等。
一个空白的守卫看起来像这样:
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Observable } from 'rxjs'; @Injectable() export class DemoAuthGuard implements CanActivate { canActivate( context: ExecutionContext, ): boolean | Promise | Observable { return true; } }
创建的守卫这个类得去实施(implements)一下 CanActivate ,然后这个类里就得添加一个 canActivate 方法,这个方法如果返回 true,就会放行请求,如果返回 false,请求就不能通过。
用 canActivate 方法的 context 参数,在方法里可以获取到请求,像这样:
const request = context.switchToHttp().getRequest();
得到了 request 以后 ,可以检查这个请求,假设我们只想检查一下这个请求里有没有包含特定的头部数据,如果包含了,并且对应的值是我们要求的,就放行这个请求,不然的话,就不放行这个请求,也就会报个异常给客户端。
return request.header('x-demo') === 'secret';
上面是 canActivate 方法 return 的东西,返回的东西就是判断了一个条件的结果,这个条件就是,看一下请求里的头部信息里面有没有 x-demo 这个东西,如果有,并且它的值是 secret ,这个方法就会返回 true,这样就会放行请求,不然就会返回 false,请求也就不能接触到它的处理器。
在控制器类,控制器里的某个方法,或者全局范围都可以绑定使用守卫:
@UseGuards(DemoAuthGuard)
使用 @UseGuards 装饰器,它装饰的就是要绑定守卫的东西,比如控制器类、控制器方法等等,把要绑定的守卫交给它就行了。