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

前言

用过expresskoa的同学,对中间件这个概念应该非常熟悉了,中间件可以拿到RequestResponse对象和next函数.

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

  • 执行任何代码
  • 对请求与响应拦截并改造
  • 结束request-response周期
  • 通过next()调用下一个中间件
  • 如果当前中间件没有结束当前request-response周期,必须调用next()函数,否则请求会处于挂起状态,阻塞整个应用

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

类中间件

创建类中间件

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

js 复制代码
// Logger.middleware.ts
import { 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方法来进行挂载

js 复制代码
// user.module.ts
import { 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驱动不能使用)
js 复制代码
export class UserModule implements NestModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes({ path: 'user', method: RequestMethod.GET});
  }
}
  • apply可以同时挂载多个中间件
js 复制代码
export class UserModule implements NestModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware, aaaMiddleware, ...)
      .forRoutes({ path: 'user', method: RequestMethod.GET});
  }
}
  • forRoutes可以使用单个string路径,多个string路径,RouteInfo对象,单个Controller,多个Controller
js 复制代码
export class AppModule implements NestModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware, NjMiddleware, ...)
      .forRoutes(UserController, NjController, ...);
  }
}
  • exclude可以用来排除不使用中间件的路径
js 复制代码
export class UserModule implements NestModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .exclude({ path: '/user/a', method: RequestMethod.GET})
      .forRoutes(UserController);
  }
}

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

函数中间件

这种方式较为简单,使用起来与类中间件一致

创建函数中间件

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

使用函数中间件

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

全局中间件

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

js 复制代码
app.use(LoggerMiddleware) // 日志中间件

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

对图片防盗感兴趣的可以看我这篇文章:你不知道的 HTTP Referer

相关推荐
星蓝_starblue13 小时前
零服务器、零数据库!开源growth-board,利用GitHub自动管理刷题/学习/求职全流程
服务器·数据库·程序人生·系统架构·node.js·github·改行学it
梦想CAD控件14 小时前
网页端CAD的图形选择、编辑与夹点操作教程
前端·javascript·node.js
万敏19 小时前
Vue3 全栈实战第四周:watch、nextTick、性能优化与 keep-alive 实战记录
vue.js·node.js·全栈
濮水大叔2 天前
为什么 AI 最擅长 React/Next.js,却很少看到真正好用的 Next.js 开源项目?
react.js·node.js·next.js
AI行业学习2 天前
Claude Code + cc-switch + Git + Node.js 全套下载+安装+配置完整版
开发语言·git·python·前端框架·node.js·html·notepad++
万亿少女的梦1682 天前
基于微信小程序、Express与MongoDB的校园失物招领系统设计
mongodb·微信小程序·node.js·express·系统设计
AI行业学习2 天前
Claude Code + cc-switch + Git + Node.js 一站式完整安装配置教程【8.3】
git·python·安全·前端框架·node.js·html·notepad++
AI行业学习2 天前
Claude Code + cc-switch + Git + Node.js 一站式完整安装配置教程(2026最新·国内可用版)
人工智能·git·python·安全·node.js·html·notepad++
用户847181054193 天前
从0开始打造自己的个人智能体(一)——Deep Agents js环境配置与对话入门
node.js·agent
减瓦3 天前
从 0.1 到 26:一个运行时的十七年进化史
node.js