前言
近年TS的兴起,Nest可谓乘风顺势,快速崛起,成为我们前端的技能必了解之一,这不我也在赶上时代的马车,快速浅浅学习一波。而前面Nest探究(一)我们已经说过了Nest的项目创建、文件架构以及swagger文档,而后我们又在Nest探究(二)中,讲述了TypeOrm相关数据库的简单操作,后续我们还会细讲。
今天我们就来说说更为复杂的中间件、过滤器、管道、守卫。
中间件
介绍
中间件是在路由处理程序之前调用对象,在Nest中,中间件函数可以访问请求和响应对象,以及应用程序请求响应周期中的 next()
中间件函数。 next()
中间件函数通常由名为 next
的变量表示。
实际上等价于express中间件,有兴趣的同学可以了解了解 express和koa,然后再引用这篇文章里面的评论,这句话概括的很好:通俗的讲,中间件就是一段管道,加入一个新的中间件就是把新的一段管道塞进原有大管道中,这段新的管道可以在自己内部对流过的数据、请求等等信息流进行任意操作(包括恶意的)。
中间件函数可以执行以下任务:
- 执行任何代码。
- 对请求和响应对象进行更改。
- 结束请求-响应周期。
- 调用堆栈中的下一个中间件函数。
- 如果当前的中间件函数没有结束请求-响应周期, 它必须调用
next()
将控制传递给下一个中间件函数。否则, 请求将被挂起。
示例
创建一个中间件类并实现RequestLoggerMiddleware
接口,然后在use()
方法中编写中间件逻辑。
typescript
import { Injectable, NestMiddleware } from "@nestjs/common"
import { NextFunction, Request, Response } from "express";
@Injectable()
export class RequestLoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
try {
const { user_id = '', user_name = '', referer = '' } = req.headers
console.log(`接口请求记录 {user_id: ${user_id}, user_name: ${decodeURI(user_name as string)
}, ip: ${req.ip}, referer: ${referer}, method: ${req.method}, url: ${req.originalUrl}, body: ${JSON.stringify(req.body)}, res: ${res.statusCode}}`)
} catch (e) {
console.log(`接口请求记录报错, ${e.stack}`)
}
next()
}
}
在模块中注册中间件 : 在需要使用中间件的模块中将中间件添加到providers
数组中,并使用forRoutes()
方法指定要应用中间件的路由。
typescript
typescriptCopy code
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { RequestLoggerMiddleware } from './logger.middleware';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(RequestLoggerMiddleware)
.forRoutes('*');
}
}
过滤器
介绍
过滤器是在路由处理程序之前或之后执行的函数。它们根据装饰器的类型在相应的时机进行执行,比如@UseFilters()
装饰器可以用于类和方法。
过滤器可以执行以下任务:
- 控制器方法执行前后进行预处理或后处理。
- 替换控制器方法的异常。
- 异常转换为可视化的异常响应。
- 改变控制器方法返回的响应对象。
- 对请求和响应对象进行更改。
示例
创建一个过滤器类并使用@Catch()
装饰器来指定要捕获的异常类型,然后实现catch()
方法来处理异常。
scala
import { Catch, ArgumentsHost } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';
@Catch()
export class AllExceptionsFilter extends BaseExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
response
.status(500)
.json({
statusCode: 500,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
全局注册过滤器: 将过滤器类添加到全局作用域中。
javascript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AllExceptionsFilter } from './all-exceptions.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new AllExceptionsFilter());
await app.listen(3000);
}
bootstrap();
管道
介绍
管道是类似于中间件的处理器,但具有更多的控制能力。它可以将数据转换为所需的格式,验证数据是否符合预期,并在将其传递给下一个处理程序之前,必要时转换或修改数据。
管道可以应用于以下场景:
- 输入数据的转换和验证。
- 控制器方法的参数绑定和验证。
- 转换输出数据。
- 错误处理和异常转换。
示例
创建一个管道类并实现PipeTransform
接口,然后在transform()
方法中编写管道逻辑。
typescript
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;
}
}
- 应用管道: 将管道添加到控制器方法的参数装饰器中。
less
import { Controller, Get, Post, Body, Param, UsePipes } from '@nestjs/common';
import { ParseIntPipe } from './parse-int.pipe';
@Controller('cats')
export class CatsController {
@Post()
@UsePipes(new ParseIntPipe())
async create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}
}
守卫
介绍
守卫是一个可以控制器方法执行的策略的函数。它可以根据装饰器的类型在不同的时机进行执行,比如@UseGuards()
装饰器可以用于类和方法。
守卫可以执行以下任务:
- 验证用户的身份或权限。
- 拒绝未经身份验证的用户。
- 根据路由处理程序是否被调用来执行逻辑。
示例
创建一个守卫类并实现CanActivate
接口,然后在canActivate()
方法中编写守卫逻辑。
typescript
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}
应用守卫 : 在需要应用守卫的控制器类或方法上使用@UseGuards()
装饰器。
kotlin
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './auth.guard';
@Controller('cats')
@UseGuards(AuthGuard)
export class CatsController {
@Get()
findAll() {
return [];
}
}
总结
以上就是Nest中常用的中间件、过滤器、管道和守卫的简介和示例。在实际项目中,它们可以帮助我们更好地控制请求流程、处理异常、验证数据等,提高代码的可维护性和可扩展性。更具体的细节更需要自己去实际操作,此处也是简要介绍用法~