2022年8月3日

Nest.js-中间件

作者 rourou

是在路由处理程序前调用的函数。可以访问请求和响应数据以及应用程序请求响应周期中的 next() 中间件函数。 next() 中间件函数通常由名为 next 的变量表示。

中间件函数可以执行以下任务:

  • 执行任何代码。
  • 对请求和响应对象进行更改。
  • 结束请求-响应周期。
  • 调用堆栈中的下一个中间件函数。
  • 如果当前的中间件函数没有结束请求-响应周期, 它必须调用 next() 将控制传递给下一个中间件函数。否则, 请求将被挂起。

您可以在函数中或在具有 @Injectable() 装饰器的类中实现自定义 Nest中间件。 这个类应该实现 NestMiddleware 接口, 而函数没有任何特殊的要求。

import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: any, res: Response, next: Function) {
    try {
      var offuscateRequest = JSON.parse(JSON.stringify(req.body));
      if (offuscateRequest != {})
        console.log(
          new Date().toString() +
            ' - [Request] ' +
            req.baseUrl +
            ' - ' +
            JSON.stringify(offuscateRequest),
        );
    } catch (error) {}
    next();
  }
}

注入依赖

中间件支持完全注入,能够注入属于同意模块的依赖项。(通过constructor)

应用中间件

中间件不能在 @Module() 装饰器中列出。需通过使用模块类的 configure() 方法来设置。包含中间件的模块必须实现 NestModule 接口。

export class UsersModule implements NestModule {
  public configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes(UsersController);
  }
}

在配置中间件时将包含路由路径的对象和请求方法传递给forRoutes()方法可以使用 async/await来实现 configure()方法的异步

中间件消费者

MiddlewareConsumer它提供了几种内置方法来管理中间件

forRoutes() 可接受一个字符串、多个字符串、对象、一个控制器类甚至多个控制器类

LoggerMiddleware 将绑定到内部定义的所有路由。 exclude() 方法轻松排除某些路由

export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(CatsController);
  }
}

apply() 方法可以使用单个中间件,也可以使用多个参数来指定多个多个中间件(通过“,”号隔离)exclude() 方法轻松排除某些路由。此方法可以采用一个字符串,多个字符串或一个 RouteInfo 对象来标识要排除的路由

函数式中间件

在没有成员,没有额外的方法,没有依赖关系的中间件可以采用函数式的中间件。(如LoggerMiddleware类)

export function LoggerMiddleware (req: any, res: Response, next: Function){   
 try {
      var offuscateRequest = JSON.parse(JSON.stringify(req.body));
      if (offuscateRequest != {})
        console.log(
          new Date().toString() +
            ' - [Request] ' +
            req.baseUrl +
            ' - ' +
            JSON.stringify(offuscateRequest),
        );
    } catch (error) {}
    next();
  }

全局中间件:中间件绑定到每个注册路由可以使用use()方法在main.ts进行全局注册