1. 中间件基本概念

nodejs中间件基本和Express的中间件完全相同,在项目中可以实现如下功能:

  • 执行代码
  • 修改原始的request和response对象
  • 结束request-response周期
  • 调用下一个(next)中间件函数
  • 如果当前中间件没有终止request-response周期,就必须继续调用下一个中间件函数

Express中包含五种类型的中间件,分别是:

  • 应用层中间件
  • 路由器层中间件
  • 错误处理中间件
  • 内置中间件
  • 第三方中间件

Express支持的中间件函数包括Fn(req,res,next)和Fn(err,req,res,next)两种形式,Nestjs仅支持前一种形式。

2. NestJs中间件使用

在NestJs官方文档中,定义了一个 LoggerMiddleware 中间件。NestJs中间件需要实现NestMiddleware并通过@Injectable()装饰器进行装饰。本文针对官方文档的中间件示例,结合Express官方文档,做一些完善和补充,示例结合了官方案例中的cat案例。在 logger.middlerware.ts 文件中,做如下定义。

  1. import { Injectable, NestMiddleware } from '@nestjs/common';
  2. import { Request, Response } from 'express';
  3. @Injectable()
  4. export class LoggerMiddleware implements NestMiddleware {
  5. use(req: Request, res: Response, next: Function) {
  6. console.log('Request...'); //在客户端有请求时,在控制台输出记录
  7. console.log(`Request URL:${req.originalUrl}`); //从请求中获取原始Url地址
  8. console.log(`Request method:${req.method}`);//获取请求的方法如GET,POST等
  9. console.log(`Request Time:${Date.now()}`);//获取请求的时间戳
  10. console.log(`Request Parameter:${req.params.catName}`);//针对catName的路由返回路由内容
  11. next();
  12. }
  13. }

3. 使用路由中间件

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

  1. import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
  2. import { LoggerMiddleware } from './common/middleware/logger.middleware';
  3. import { CatsModule } from './cats/cats.module';
  4. @Module({
  5. imports: [CatsModule],
  6. })
  7. export class AppModule implements NestModule {
  8. configure(consumer: MiddlewareConsumer) {
  9. consumer
  10. .apply(LoggerMiddleware) //应用LoggerMiddleware中间件
  11. .forRoutes('cats/:catName'); //指定中间件的应用路径/cats/:catName
  12. //.forRoutes('cats');
  13. //也可以通过如下方式指定包含中间件的请求方法
  14. // .forRoutes({ path: 'cats', method: RequestMethod.GET });
  15. //也可以使用通配符来匹配路径,如以下示例
  16. //forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });
  17. // 通过以下方法来针对不同控制器使用中间件,也可以传递一个由逗号分隔的控制器列表
  18. //.forRoutes(CatsController);
  19. // 通过exclude和路径方法来排除特定路径
  20. //.exclude(
  21. //{ path: 'cats', method: RequestMethod.GET },
  22. //{ path: 'cats', method: RequestMethod.POST })
  23. }
  24. }

4. 其他中间件形式

4.1 函数式中间件

一个没有额外的方法和依赖关系的中间件也可以转换为函数式中间件,这和Express中的中间件形式非常接近。例如上述中间件可以修改为:

  1. export function logger(req, res, next) {
  2. console.log(`Request...`);
  3. next();
  4. };

在模块中应用:

  1. consumer
  2. .apply(logger)
  3. .forRoutes(CatsController);

4.2 调用多个中间件

  1. consumer.apply(cors(), helmet(), logger).forRoutes(CatsController);

4.3 全局中间件

可以使用由INestApplication 提供的use()方法来定义全局中间件。

  1. const app = await NestFactory.create(AppModule);
  2. app.use(logger);
  3. await app.listen(3000);