Nest探究(三):中间件、过滤器、管道、守卫

前言

近年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;
  }
}
  1. 应用管道: 将管道添加到控制器方法的参数装饰器中。
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中常用的中间件、过滤器、管道和守卫的简介和示例。在实际项目中,它们可以帮助我们更好地控制请求流程、处理异常、验证数据等,提高代码的可维护性和可扩展性。更具体的细节更需要自己去实际操作,此处也是简要介绍用法~

相关推荐
昨天;明天。今天。3 小时前
案例-表白墙简单实现
前端·javascript·css
安冬的码畜日常3 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
小御姐@stella3 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing3 小时前
【React】增量传输与渲染
前端·javascript·面试
GISer_Jing3 小时前
WebGL在低配置电脑的应用
javascript
万叶学编程6 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js
天涯学馆9 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF9 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi9 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器