前言

用过expresskoa的同学,对中间件这个概念应该十分相熟了,中间件能够拿到RequestResponse对象和next函数.

一般来讲中间件有以下作用:

  • 执行任何代码
  • 对申请与响应拦挡并革新
  • 完结request-response周期
  • 通过next()调用下一个中间件
  • 如果以后中间件没有完结以后request-response周期,必须调用next()函数,否则申请会处于挂起状态,阻塞整个利用

中间件个别有两种:类中间件函数中间件

类中间件

创立类中间件

应用@Injectable()装璜器,并且须要实现NestMiddleware接口(use办法)

// Logger.middleware.tsimport { Injectable, NestMiddleware } from "@nestjs/common";import { Request, Response } from "express";@Injectable()export class LoggerMiddleware implements NestMiddleware {    use(req: Request, res: Response, next: () => void) {        console.log('logger middleware', `url: ${req.url}`);        next();    }}

应用类中间件

类两头创立完之后,须要在模块中进行挂载,但@Module装璜器并没有中间件的相干配置,咱们须要让module类实现NestModule接口,实现外面configure办法来进行挂载

// user.module.tsimport { Module, NestModule } from '@nestjs/common';import { UserService } from './user.service';import { UserController } from './user.controller';import { LoggerMiddleware } from '../middleware/Logger.middleware';@Module({  controllers: [UserController],  providers: [UserService]})export class UserModule implements NestModule {  configure(consumer) {    consumer      .apply(LoggerMiddleware)      .forRoutes(UserController);  }}
  • apply办法示意挂载的是哪个中间件
  • forRoutes办法示意对哪个申请门路起作用,这种形式与app.use(path, middleware)作用是一样,只针对局部门路起作用
  • 当给forRoutes办法传递的是一个controller控制器时,那么该中间件则对整个控制器下的门路失效

比方这里传递的是UserController控制器,那么针对该控制器下的门路都会失效

  • forRootes办法还能做更具体的配置,比方能够针对特定的申请办法、申请门路能够应用正则匹配(须要留神的是应用fastify驱动不能应用)
export class UserModule implements NestModule {  configure(consumer) {    consumer      .apply(LoggerMiddleware)      .forRoutes({ path: 'user', method: RequestMethod.GET});  }}
  • apply能够同时挂载多个中间件
export class UserModule implements NestModule {  configure(consumer) {    consumer      .apply(LoggerMiddleware, aaaMiddleware, ...)      .forRoutes({ path: 'user', method: RequestMethod.GET});  }}
  • forRoutes能够应用单个string门路,多个string门路,RouteInfo对象,单个Controller,多个Controller
export class AppModule implements NestModule {  configure(consumer) {    consumer      .apply(LoggerMiddleware, NjMiddleware, ...)      .forRoutes(UserController, NjController, ...);  }}
  • exclude能够用来排除不应用中间件的门路
export class UserModule implements NestModule {  configure(consumer) {    consumer      .apply(LoggerMiddleware)      .exclude({ path: '/user/a', method: RequestMethod.GET})      .forRoutes(UserController);  }}

须要留神的是forRoutes须要最初调用

函数中间件

这种形式较为简单,应用起来与类中间件统一

创立函数中间件

export function LoggerMiddleware(req: Request, res: Response, next: () => void) {    console.log('logger middleware', `url: ${req.url}`);    next();}

应用函数中间件

export class UserModule implements NestModule {  configure(consumer) {    consumer      .apply(LoggerMiddleware)      .exclude({ path: '/user/a', method: RequestMethod.GET})      .forRoutes(UserController);  }}

全局中间件

能够间接在入口文件main.ts中应用app.use来挂载中间件,这样挂载的中间件将全局失效

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

中间件其实能够用来实现很多性能,比方:日志零碎、cors跨域解决、图片防盗等...

对图片防盗感兴趣的能够看我这篇文章:你不晓得的 HTTP Referer