Coder Social home page Coder Social logo

andrewda / throttler Goto Github PK

View Code? Open in Web Editor NEW

This project forked from nestjs/throttler

0.0 1.0 0.0 4.97 MB

A rate limiting module for NestJS to work with Fastify, Express, GQL, Websockets, and RPC 🧭

Home Page: https://nestjs.com

License: MIT License

JavaScript 2.04% TypeScript 97.96%

throttler's Introduction

Nest Logo

A progressive Node.js framework for building efficient and scalable server-side applications.

NPM Version Package License NPM Downloads Travis Linux Coverage Discord Backers on Open Collective Sponsors on Open Collective

Description

A Rate-Limiter for NestJS, regardless of the context.

For an overview of the community storage providers, see Community Storage Providers.

This package comes with a couple of goodies that should be mentioned, first is the ThrottlerModule.

Table of Contents

Usage

ThrottlerModule

The ThrottleModule is the main entry point for this package, and can be used in a synchronous or asynchronous manner. All the needs to be passed is the ttl, the time to live in seconds for the request tracker, and the limit, or how many times an endpoint can be hit before returning a 429.

import { APP_GUARD } from '@nestjs/core';
import { ThrottlerGuard, ThrottlerModule } from 'nestjs-throttler';

@Module({
  imports: [
    ThrottlerModule.forRoot({
      ttl: 60,
      limit: 10,
    }),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
  ],
})
export class AppModule {}

The above would mean that 10 requests from the same IP can be made to a single endpoint in 1 minute.

@Module({
  imports: [
    ThrottlerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        ttl: config.get('THROTTLE_TTL'),
        limit: config.get('THROTTLE_LIMIT'),
      }),
    }),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
  ],
})
export class AppModule {}

The above is also a valid configuration for asynchronous registration of the module.

NOTE: If you add the ThrottlerGuard to your AppModule as a global guard then all the incoming requests will be throttled by default. This can also be omitted in favor of @UseGuards(ThrottlerGuard). The global guard check can be skipped using the @SkipThrottle() decorator mentioned later.

Example with @UseGuards(ThrottlerGuard):

// app.module.ts
@Module({
  imports: [
    ThrottlerModule.forRoot({
      ttl: 60,
      limit: 10,
    }),
  ],
})
export class AppModule {}

// app.controller.ts
@Controller()
export class AppController {
  @UseGuards(ThrottlerGuard)
  @Throttle(5, 30)
  normal() {}
}

Decorators

@Throttle()

@Throttle(limit: number = 20, ttl: number = 60)

This decorator will set THROTTLER_LIMIT and THROTTLER_TTL metadatas on the route, for retrieval from the Reflector class. Can be applied to controllers and routes.

@SkipThrottle()

@SkipThrottle(skip = true)

This decorator can be used to skip a route or a class or to negate the skipping of a route in a class that is skipped.

@SkipThrottle()
@Controller()
export class AppController {
  @SkipThrottle(false)
  dontSkip() {}

  doSkip() {}
}

In the above controller, dontSkip would be counted against and rate-limited while doSkip would not be limited in any way.

Ignoring specific user agents

You can use the ignoreUserAgents key to ignore specific user agents.

@Module({
  imports: [
    ThrottlerModule.forRoot({
      ttl: 60,
      limit: 10,
      ignoreUserAgents: [
        // Don't throttle request that have 'googlebot' defined in them.
        // Example user agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
        /googlebot/gi,

        // Don't throttle request that have 'bingbot' defined in them.
        // Example user agent: Mozilla/5.0 (compatible; Bingbot/2.0; +http://www.bing.com/bingbot.htm)
        new RegExp('bingbot', 'gi'),
      ],
    }),
  ],
})
export class AppModule {}

ThrottlerStorage

Interface to define the methods to handle the details when it comes to keeping track of the requests.

Currently the key is seen as an MD5 hash of the IP the ClassName and the MethodName, to ensure that no unsafe characters are used and to ensure that the package works for contexts that don't have explicit routes (like Websockets and GraphQL).

The interface looks like this:

export interface ThrottlerStorage {
  getRecord(key: string): Promise<number[]>;
  addRecord(key: string, ttl: number): Promise<void>;
}

So long as the Storage service implements this interface, it should be usable by the ThrottlerGuard.

Working with Websockets

There are some things to take keep in mind when working with websockets:

  • You cannot bind the guard with APP_GUARD or app.useGlobalGuards() due to how Nest binds global guards.
  • When a limit is reached, Nest will emit an exception event, so make sure there is a listener ready for this.

Working with GraphQL

To get the ThrottlerModule to work with the GraphQL context, a couple of things must happen.

  • You must use Express and apollo-server-express as your GraphQL server engine. This is the default for Nest, but the apollo-server-fastify package does not currently support passing res to the context, meaning headers cannot be properly set.
  • When configuring your GraphQLModule, you need to pass an option for context in the form of ({ req, res}) => ({ req, res }). This will allow access to the Express Request and Response objects, allowing for the reading and writing of headers.

Community Storage Providers

Feel free to submit a PR with your custom storage provider being added to this list.

throttler's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar jmcdo29 avatar kamilmysliwiec avatar kkoomen avatar renovate-bot avatar tony133 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.