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

相关推荐
真的很上进几秒前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
噢,我明白了3 小时前
同源策略:为什么XMLHttpRequest不能跨域请求资源?
javascript·跨域
sanguine__4 小时前
APIs-day2
javascript·css·css3
关你西红柿子4 小时前
小程序app封装公用顶部筛选区uv-drop-down
前端·javascript·vue.js·小程序·uv
济南小草根4 小时前
把一个Vue项目的页面打包后再另一个项目中使用
前端·javascript·vue.js
小木_.4 小时前
【python 逆向分析某有道翻译】分析有道翻译公开的密文内容,webpack类型,全程扣代码,最后实现接口调用翻译,仅供学习参考
javascript·python·学习·webpack·分享·逆向分析
Aphasia3115 小时前
一次搞懂 JS 对象转换,从此告别类型错误!
javascript·面试
m0_748256565 小时前
Vue - axios的使用
前端·javascript·vue.js
m0_748256345 小时前
QWebChannel实现与JS的交互
java·javascript·交互
胡西风_foxww5 小时前
【es6复习笔记】函数参数的默认值(6)
javascript·笔记·es6·参数·函数·默认值