【NestJS系列】核心概念:Middleware中间件
2023-08-28 20:21:24    博客园
前言

用过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

关键词:

下一篇: 女子半月被缅北男友骗光850万 平日里对其嘘寒问暖
上一篇: 最后一页