nest 中间件

时间:2023-01-05 浏览:178 分类:NestJS

第一步:

实现中间件逻辑,以user中间件为例

// user.middleware.ts
import {Injectable, NestMiddleware} from '@nestjs/common';
import {Request, Response, NextFunction} from 'express';

@Injectable()
export class UserMiddleware implements NestMiddleware {
    async use(req: Request, res: Response, next: NextFunction) {
        console.log('UserMiddleware');
        next();
    }
}

中间件类必须继承于 NestMiddleware,并且完善user() 方法,中间件传递控制权必须调用next() 函数

第二步:

在当下模块中引入中间件

// user.module.ts
import {MiddlewareConsumer, NestModule} from "@nestjs/common";
import {UserMiddleware} from "./user.middleware";

@Module({
    controllers: [UserController],
    providers: [UserService]
})
export class UserModule implements NestModule {
    configure(consumer: MiddlewareConsumer) {
        consumer
            .apply(UserMiddleware)  //引入中间件类
            .exclude('/user/(.*)')  //被排除的路由
            .forRoutes(UserController)  //匹配执行中间件的控制器
    }
}

注意:

exclude() 排除路由需放在forRoutes方法之上,并且支持模糊匹配,注意exclude匹配规则是path-to-regexp 这里必须用(.*) 不能使用*

//匹配user开头的任意路由,注意这里必须用(.*) 不能使用*
.exclude('user/(.*)')

//也支持多行书写匹配
.exclude(
  { path: 'user', method: RequestMethod.GET },
  { path: 'user', method: RequestMethod.POST },
  'user/(.*)',
)


forRoutes() 指定路由可以具体请求参数,比如:

// 支持模糊匹配,比如user/* 另 RequestMethod.All 可以为 GET,POST,PUT等请求方式
.forRoutes({ path: 'user', method: RequestMethod.All });
// 模糊匹配
.forRoutes({ path: 'user/*', method: RequestMethod.All });

函数中间件

如果类中间件它没有成员属性,也没有额外的方法,也没有依赖关系。为什么我们不能用一个简单的函数而不是一个类来定义它呢?事实上,我们可以使用函数式中间件,每当中间件不需要任何依赖项时,应考虑使用更简单的函数中间件替代。如下:

// user.middleware.ts

import { Request, Response, NextFunction } from 'express';

export function logger(req: Request, res: Response, next: NextFunction) {
  console.log(`UserMiddleware...`);
  next();};
}

然后在模块中引入:

// user.module.ts

consumer
  .apply(UserMiddleware)
  .forRoutes(UserController);

多中间件

直接在apply() 方法中引入即可

configure(consumer: MiddlewareConsumer) {
    consumer
        .apply(cors(), helmet(), logger)
        .exclude('user/(.*)')
        .forRoutes(UserController)
}

全局中间件

如果我们想一次将中间件绑定到每个已注册的路由,我们可以使用实例提供的 use() 方法:

// main.ts

const app = await NestFactory.create(AppModule);
app.use(UserMiddleware);
await app.listen(3000);

注意无法访问全局中间件中的 DI 容器。在使用 app.use() 时,可以使用函数式中间件。或者,可以使用类中间件并在 AppModule(或任何其他模块)中使用 .forRoutes('*') 来使用它。