Rate Limiting in NestJS: A Complete Guide with Examples
Rate Limiting in NestJS: A Complete Guide with Examples

Rate Limiting in NestJS: A Complete Guide with Examples

Rate limiting is a crucial technique to control the number of requests a client can make to your API within a specific time frame. It helps prevent abuse, ensures fair usage, and protects your server from being overwhelmed. NestJS provides a built-in @nestjs/throttler package to implement rate limiting easily.

In this article, we’ll cover the following topics in detail:

  1. Install the Required Package
  2. Controller with Custom Rate Limits
  3. Skipping Rate Limiting with @SkipThrottle
  4. Using ThrottlerGuard with GraphQL
  5. Role-Based Rate Limiting

Let’s dive in!


1. Install the Required Package

To get started, you need to install the @nestjs/throttler package:

npm install @nestjs/throttler        

This package provides the necessary tools to implement rate limiting in your NestJS application.


2. Controller with Custom Rate Limits

Once the package is installed, you can configure rate limiting globally and apply custom rate limits to specific routes.

Global Rate Limiting

First, configure the ThrottlerModule in your AppModule:

import { Module } from '@nestjs/common';
import { ThrottlerModule } from '@nestjs/throttler';
import { AppController } from './app.controller';

@Module({
  imports: [
    ThrottlerModule.forRoot({
      throttlers: [
        {
          ttl: 60000, // Time-to-live in milliseconds (1 minute)
          limit: 10, // Maximum number of requests within the TTL
        },
      ],
    }),
  ],
  controllers: [AppController],
})
export class AppModule {}        

Custom Rate Limits for Specific Routes

You can override the global rate limit for specific routes using the @Throttle() decorator:

import { Controller, Get } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';

@Controller()
export class AppController {
  @Get('public')
  @Throttle({ default: { ttl: 30000, limit: 5 } }) // 5 requests per 30 seconds
  getPublicData() {
    return 'This is public data.';
  }

  @Get('private')
  getPrivateData() {
    return 'This is private data.';
  }
}        

In this example:

  • The public route allows 5 requests per 30 seconds.
  • The private route uses the global rate limit (10 requests per minute).


3. Skipping Rate Limiting with @SkipThrottle

Sometimes, you may want to exclude certain routes or controllers from rate limiting. The @SkipThrottle decorator allows you to do this.

Skip a Specific Route

import { Controller, Get } from '@nestjs/common';
import { SkipThrottle } from '@nestjs/throttler';

@Controller()
export class AppController {
  @Get('health')
  @SkipThrottle() // Skip rate limiting for this route
  checkHealth() {
    return 'Service is healthy.';
  }
}        

Skip an Entire Controller

import { Controller, Get } from '@nestjs/common';
import { SkipThrottle } from '@nestjs/throttler';

@SkipThrottle() // Skip rate limiting for all routes in this controller
@Controller('status')
export class StatusController {
  @Get()
  getStatus() {
    return 'Service is running.';
  }
}        

4. Using ThrottlerGuard with GraphQL

The ThrottlerGuard can also be used with GraphQL APIs. However, since GraphQL uses a different execution context, you need to customize the guard to extract the request and response objects.

Custom GqlThrottlerGuard

Create a custom guard for GraphQL:

import { ExecutionContext, Injectable } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { ThrottlerGuard } from '@nestjs/throttler';

@Injectable()
export class GqlThrottlerGuard extends ThrottlerGuard {
  getRequestResponse(context: ExecutionContext) {
    const gqlContext = GqlExecutionContext.create(context); // Get GraphQL context
    const ctx = gqlContext.getContext(); // Extract request and response
    return { req: ctx.req, res: ctx.res };
  }
}        

Apply the Custom Guard

Update your AppModule to use the custom guard:

import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { ThrottlerModule } from '@nestjs/throttler';
import { GqlThrottlerGuard } from './gql-throttler.guard';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';

@Module({
  imports: [
    ThrottlerModule.forRoot({
      throttlers: [
        {
          ttl: 60000, // 1 minute
          limit: 10, // 10 requests per minute
        },
      ],
    }),
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
       playground: true,
      context: ({ req, res }) => ({ req, res }),
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
    }),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: GqlThrottlerGuard, // Apply the custom GraphQL guard
    },
  ],
})
export class AppModule {}        

5. Role-Based Rate Limiting

You can implement role-based rate limiting by extending the ThrottlerGuard and customizing the rate limits based on the user's role.

Custom RoleBasedThrottlerGuard

import { ExecutionContext, Injectable } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';

@Injectable()
export class RoleBasedThrottlerGuard extends ThrottlerGuard {
  protected async getRateLimit(context: ExecutionContext): Promise<number> {
    const request = context.switchToHttp().getRequest();
    const user = request.user; // Assuming user is attached to the request

    // Apply different rate limits based on user role
    if (user?.role === 'admin') {
      return 100; // Admins get 100 requests per minute
    } else if (user?.role === 'manager') {
      return 50; // Manager users get 50 requests per minute
    } else {
      return 10; // Regular users get 10 requests per minute
    }
  }
}        

Apply the Role-Based Guard

Update your AppModule to use the role-based guard:

import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { ThrottlerModule } from '@nestjs/throttler';
import { RoleBasedThrottlerGuard } from './role-based-throttler.guard';

@Module({
  imports: [
    ThrottlerModule.forRoot({
      throttlers: [
        {
          ttl: 60000, // 1 minute
          limit: 10, // Default limit (overridden by RoleBasedThrottlerGuard)
        },
      ],
    }),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: RoleBasedThrottlerGuard, // Apply the role-based guard
    },
  ],
})
export class AppModule {}        

Conclusion

Rate limiting is a powerful tool to protect your API from abuse and ensure fair usage. With NestJS and the @nestjs/throttler package, you can easily implement global and custom rate limits, skip rate limiting for specific routes, use it with GraphQL, and even implement role-based rate limiting.

By following this guide, you can build a robust and secure API with NestJS. Let me know if you have further questions! ??

Check out the full implementation here: ?? GitHub Repository

?? Follow Me for More Content:

?? Happy Learning! ??

#NestJS #RateLimiting #API #WebDevelopment #Backend #NodeJS #GraphQL #RESTAPI #Coding #Developer


要查看或添加评论,请登录

Syed Ali Hamza Zaidi ?的更多文章

社区洞察

其他会员也浏览了