返回

从nestjs-rate-limiter学写一个拦截器

前端

想理解拦截器,先要理解nestjs的全局拦截器是什么?有什么作用?Nest.js的核心功能之一是模块,每个模块都可以在自己的作用域中使用自己的拦截器和管道。但是,对于想对所有模块应用相同的拦截器的情况,Nest.js提供了一个全局拦截器,这样我们就可以对任何一个模块或控制器启用全局的拦截器,例如用来记录请求和响应数据、执行身份验证或速率限制。

我们先来看看现有的限流中间件是什么样子的。下面是nest-rate-limiter项目的代码:

// src/limiter.interceptor.ts
// 导入RateLimiterGuard类
import { RateLimiterGuard } from './rate-limiter.guard';

// 导出RateLimiterInterceptor类
export class RateLimiterInterceptor implements NestInterceptor {
  // 类的构造函数
  constructor(private readonly limiter: RateLimiterGuard) {}

  // 实现Intercept方法
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    // 从执行上下文中获取请求
    const request = context.switchToHttp().getRequest();

    // 执行限流守卫
    return this.limiter.canActivate(context).pipe(
      // 映射守卫的执行结果
      map(() => next.handle()),
    );
  }
}

上文创建了一个类,并实现了NestInterceptor接口。NestInterceptor接口强制要求实现intercept方法,该方法接受两个参数:context和next。context参数提供有关当前正在执行的请求的信息,而next参数允许将控制权传递给下一个拦截器或控制器处理程序。

接下来,我们看看拦截器的使用方式。下面是nest-rate-limiter项目的代码:

// src/limiter.module.ts
import { Module, MiddlewareConsumer } from '@nestjs/common';
import { RateLimiterMiddleware } from './rate-limiter.middleware';

@Module({
  providers: [],
})
export class RateLimiterModule {
  // 在MiddlewareConsumer上配置中间件
  configure(consumer: MiddlewareConsumer): void {
    consumer.apply(RateLimiterMiddleware).forRoutes('*');
  }
}

这里,RateLimiterMiddleware是Nest.js的中间件,当请求到达时,该中间件将首先执行。中间件使用RateLimiterGuard类来检查请求是否受到速率限制。

最后,我们来写一个自定义的拦截器。下面是代码:

// src/custom-limiter.interceptor.ts
// 导入Injectable装饰器
import { Injectable, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';

// 定义一个Injectable装饰器
@Injectable()
export class CustomLimiterInterceptor implements NestInterceptor {
  // 实现intercept方法
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    // 从执行上下文中获取请求
    const request = context.switchToHttp().getRequest();

    // 在这里执行自定义的速率限制逻辑

    // 执行下一个拦截器或控制器处理程序
    return next.handle();
  }
}

最后,我们来注册自定义拦截器。下面是代码:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CustomLimiterInterceptor } from './custom-limiter.interceptor';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService, CustomLimiterInterceptor],
})
export class AppModule {
  // 在构造函数中使用useGlobalInterceptors方法注册拦截器
  constructor(private readonly limiter: CustomLimiterInterceptor) {
    // 注册拦截器
    NestFactory.create(AppModule).useGlobalInterceptors(limiter).listen(3000);
  }
}

现在,我们的自定义拦截器已经注册,它将在每个请求上执行。