当前位置:科技动态 > 【NestJS系列】核心概念:中间件

【NestJS系列】核心概念:中间件

  • 发布:2023-10-01 16:59

前言

使用过expresskoa的同学应该对中间件的概念非常熟悉。中间件可以从 RequestResponse 对象和 next 函数获得。

一般来说,中间件有以下功能:

  • 执行任何代码
  • 请求和响应的拦截和转换
  • 结束请求-响应循环
  • 通过 next() 调用下一个中间件
  • 如果当前中间件没有结束当前的请求-响应循环,则必须调用next()函数,否则请求将处于待处理状态,阻塞整个应用程序

中间件一般有两类:类中间件函数中间件

类中间件

创建类中间件

使用@Injectable()装饰器,并且需要实现NestMiddleware接口(use方法)

// Logger.middleware.ts
从“@nestjs/common”导入{ Injectable, NestMiddleware };
从“express”导入{请求,响应};

@Injectable()
导出类 LoggerMiddleware 实现 NestMiddleware {
    use(req: 请求,res: 响应,下一个:() => void) {
        console.log('记录器中间件', `url: ${req.url}`);
        下一个();
    }
}

使用类中间件

类创建后需要挂载到模块中,但是@Module装饰器没有中间件的相关配置。我们需要让module类实现NestModule接口,实现里面的configure方法来挂载

// user.module.ts
从'@nestjs/common'导入{模块,NestModule};
从 './user.service' 导入 { UserService };
从'./user.controller'导入{UserController};
从'../middleware/Logger.middleware'导入{LoggerMiddleware};
@模块({
  控制器:[用户控制器],
  提供者:[用户服务]
})
导出类 UserModule 实现 NestModule {
  配置(消费者){
    消费者
      .apply(Logger中间件)
      .forRoutes(UserController);
  }
}
  • apply方法指示挂载了哪个中间件
  • forRoutes 方法指示它在哪个请求路径上工作。该方法与app.use(path, middleware)效果相同。它只适用于部分路径
  • forRoutes方法经过一个控制器控制器时,那么中间件就会在整个控制器下的路径上生效

比如这里传入的是UserController控制器,那么这个控制器下的路径就会生效

  • forRootes方法还可以进行更详细的配置。比如针对特定的请求方法和请求路径可以使用正则匹配(需要注意的是,不能使用fastify驱动)
导出类 UserModule 实现 NestModule {
  配置(消费者){
    消费者
      .apply(Logger中间件)
      .forRoutes({ 路径: '用户', 方法: RequestMethod.GET});
  }
}
  • 申请可以同时挂载多个中间件
导出类 UserModule 实现 NestModule {
  配置(消费者){
    消费者
      .apply(LoggerMiddleware, aaaMiddleware, ...)
      .forRoutes({ 路径: '用户', 方法: RequestMethod.GET});
  }
}
  • forRoutes 可以使用单个 string 路径、多个 string 路径、RouteInfo 对象、单个控制器,多个控制器
导出类AppModule实现NestModule {
  配置(消费者){
    消费者
      .apply(LoggerMiddleware, NjMiddleware, ...).forRoutes(UserController, NjController, ...);
  }
}
  • exclude可用于排除不使用中间件的路径
导出类 UserModule 实现 NestModule {
  配置(消费者){
    消费者
      .apply(Logger中间件)
      .exclude({ 路径: '/user/a', 方法: RequestMethod.GET})
      .forRoutes(UserController);
  }
}

需要注意的是forRoutes需要最后调用

函数中间件

这个方法比较简单,和类中间件一致

创建函数中间件

导出函数 LoggerMiddleware(req: 请求, res: 响应, next: () => void) {
    console.log('记录器中间件', `url: ${req.url}`);
    下一个();
}

使用函数中间件

导出类 UserModule 实现 NestModule {
  配置(消费者){
    消费者
      .apply(Logger中间件)
      .exclude({ 路径: '/user/a', 方法: RequestMethod.GET})
      .forRoutes(UserController);
  }
}

全局中间件

可以直接在入口文件main.ts中使用app.use来挂载中间件,这样挂载的中间件就会全局生效

app.use(LoggerMiddleware) // 日志中间件

中间件其实可以用来实现很多功能,比如:日志系统、cors跨域处理、图片防盗等等......

如果您对防盗图感兴趣,可以阅读我的文章:你不知道的HTTP Referer

相关文章