中间件
中间件是在路由处理程序之前调用的函数。中间件函数 可以访问请求和响应对象,以及应用程序请求。下一个中间件函数通常由名为 next
的变量表示。
中间件函数可以执行以下任务:
- 对请求和响应对象进行更改。
- 调用堆栈中的下一个中间件函数。
- 如果当前中间件函数没有结束请求-响应周期,则必须调用
next()
将控制权传递给下一个中间件函数。否则,请求将保持挂起状态。
可以在 函数
中实现自定义 Nest 中间件,也可以在具有 @Injectable()
装饰器的类中实现。该类应实现 NestMiddleware
接口,而该函数没有任何特殊要求。
logger.middleware.ts
使用 calss
方法定义一个中间件
import { Injectable, NestMiddleware, Body } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}
也可以使用 函数
定义中间件
export function logger(req: Request, res: Response, next: NextFunction) {
console.log(`LOGGER...`);
next();
};
使用中间件
基础使用
实现 NestModule
接口,在 forRoutes
传入要使用中间件的 controller
的路径
app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('cats');
}
}
cat.controller
@Controller("cats")
export class CatsController{}
指定请求方法
forRoutes 可以传入一个对象,
path
表示的是要使用的controller
名称,method
表示允许使用中间件的方法
在下面的例子中,我们配置
method
为get
,那么在cats
中的post
方法无法使用 中间件
import { Module, NestModule, RequestMethod, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'cats', method: RequestMethod.GET });
}
}
路由通配符
可以使用正则表达式,例如,星号 用作通配符,并将匹配任意字符组合:
import { Module, NestModule, RequestMethod, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes({
path: 'cat*', method: RequestMethod.ALL
});
}
}
传入控制器
可以直接传入控制器
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
import { CatsController } from './cats/cats.controller';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes(CatsController);
}
}
排除路由
我们可以使用 exclude()
方法轻松排除某些路由,下图的方式是排除 cats
路由中的 Get
方法
consumer
.apply(LoggerMiddleware)
.exclude(
{ path: 'cats', method: RequestMethod.GET },
)
.forRoutes(CatsController);
多个中间件
多个中间件使用逗号连接
consumer
.apply(LoggerMiddleware,logger)
.forRoutes(CatsController,ListController);
全局中间件
import { logger } from './middlewares/logger.middleware';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
generateDocument(app);
// *** 中间件
app.use(logger)
// ***
app.useGlobalPipes(new ValidationPipe());
await app.listen(3001);
}
bootstrap();