中间件是在路由处理程序之前调用的函数。在中间件中可以访问请求和响应对象,也可以访问next()函数,当中间件处理完毕后必须调用next()将控制权交给下一个中间件,否则,请求将会被挂起。中间件的处理如下图:
26423803-CBC8-4F17-9A0F-FA0446BAF1E2.png

1.自定义Middleware

自定义Middleware只需要做两件事,第一是使用@Injectable装饰器将中间件注入到IOC容器,第二步是实现NestMiddleware接口并重写该接口的use方法,use方法接收请求对象、响应对象、next函数3个参数,注意必须调用next()将控制权交给下一个中间件,否则请求将会被挂起。未使用@Injectable装饰器修饰中间件仍能正常访问。

  1. /**
  2. * src/common/middleware
  3. *
  4. * 自定义middleware只需两步操作,第一使用@Injectable装饰器将中间件注入到IOC容器,
  5. * 第二步是实现NestMiddleware接口重写该接口的use方法。
  6. */
  7. import { Injectable, NestMiddleware } from '@nestjs/common';
  8. @Injectable()
  9. export class LoggerMiddleware implements NestMiddleware {
  10. /*
  11. * req 为请求对象,res为响应对象,next()用于调用下一个中间件
  12. */
  13. use(req: any, res: any, next: () => void) {
  14. console.log('我是Logger Middleware');
  15. next();
  16. }
  17. }

在module中使用中间件,使用中间件需要实现NestModule并重写configure函数,configure函数接收一个中间件消费者对象,通过调用该对象的apply可以使用Middleware,也可以使用exclude()排除不需要被中间件处理的请求,也可以使用forRoutes对包含某个路由前缀进行处理。

  1. //app.module.ts
  2. import {
  3. Module,
  4. NestModule,
  5. MiddlewareConsumer,
  6. RequestMethod,
  7. } from '@nestjs/common';
  8. import { AppController } from './app.controller';
  9. import { AppService } from './app.service';
  10. import { LoggerMiddleware } from './common/middleware/logger.middleware';
  11. @Module({
  12. imports: [],
  13. controllers: [AppController],
  14. providers: [AppService],
  15. })
  16. export class AppModule implements NestModule {
  17. configure(consumer: MiddlewareConsumer) {
  18. /**
  19. * exclude用于排除请求,例如下面例子中表示排除路径为/getUser并且请求类型为get的请求。
  20. * forRoutes表示中间件只应用于请求url前缀为app的请求。
  21. * apply()中可以传入多个中间件,以逗号隔开
  22. */
  23. consumer
  24. .apply(LoggerMiddleware)
  25. .exclude({ path: '/getUser', method: RequestMethod.GET })
  26. .forRoutes('app');
  27. }
  28. }
  1. //app.controller.ts
  2. import { Controller, Get } from '@nestjs/common';
  3. import { AppService } from './app.service';
  4. @Controller('/app')
  5. export class AppController {
  6. constructor(private readonly appService: AppService) {}
  7. //当访问localhost:3000/app/hello时请求会被中间件拦截到
  8. @Get('/hello')
  9. getHello(): string {
  10. return this.appService.getHello();
  11. }
  12. }

2.函数Middleware

  1. import { Request, Response, NextFunction } from 'express';
  2. /*
  3. * req 为请求对象,res为响应对象,next()用于调用下一个中间件
  4. */
  5. export default function (req: Request, res: Response, next: NextFunction) {
  6. console.log('我是函数中间件....');
  7. next();
  8. }

2.使用全局中间件

  1. import FuncMiddleware from './common/middleware/func.middleware';
  2. const app = await NestFactory.create(AppModule);
  3. //使用create()创建的INestApplication实例,通过该实例的use()调用中间件,注意use()调用的中间件必须是函数中间件
  4. app.use(logger);
  5. await app.listen(3000)