实现中间件逻辑,以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('*') 来使用它。
www.haizhuan.tk