All Projects → iamolegga → nestjs-ratelimiter

iamolegga / nestjs-ratelimiter

Licence: MIT license
Distributed consistent flexible NestJS rate limiter based on Redis

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to nestjs-ratelimiter

Throttler
A rate limiting module for NestJS to work with Fastify, Express, GQL, Websockets, and RPC 🧭
Stars: ✭ 145 (+195.92%)
Mutual labels:  nest, rate-limiter, nestjs
Config
Configuration module for Nest framework (node.js) 🍓
Stars: ✭ 161 (+228.57%)
Mutual labels:  nest, nestjs
Passport
Passport module for Nest framework (node.js) 🔑
Stars: ✭ 211 (+330.61%)
Mutual labels:  nest, nestjs
Jwt
JWT utilities module based on the jsonwebtoken package 🔓
Stars: ✭ 232 (+373.47%)
Mutual labels:  nest, nestjs
Elasticsearch
Elasticsearch module based on the official elasticsearch package 🌿
Stars: ✭ 176 (+259.18%)
Mutual labels:  nest, nestjs
Nest Event
Event handling with decorators for NestJS Framework
Stars: ✭ 128 (+161.22%)
Mutual labels:  nest, nestjs
Nest User Auth
A starter build for a back end which implements managing users with MongoDB, Mongoose, NestJS, Passport-JWT, and GraphQL.
Stars: ✭ 145 (+195.92%)
Mutual labels:  nest, nestjs
Cool Admin Api
cool-admin-api 是基于egg.js、typeorm、jwt等封装的api开发脚手架、快速开发api接口
Stars: ✭ 188 (+283.67%)
Mutual labels:  nest, nestjs
Mongoose
Mongoose module for Nest framework (node.js) 🍸
Stars: ✭ 191 (+289.8%)
Mutual labels:  nest, nestjs
Notadd
A microservice development architecture based on nest.js. —— 基于 Nest.js 的微服务开发架构。
Stars: ✭ 2,556 (+5116.33%)
Mutual labels:  nest, nestjs
Stator
Stator, your go-to template for the perfect stack. 😍🙏
Stars: ✭ 217 (+342.86%)
Mutual labels:  nest, nestjs
Crud
NestJs CRUD for RESTful APIs
Stars: ✭ 2,709 (+5428.57%)
Mutual labels:  nest, nestjs
Nest
A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications on top of TypeScript & JavaScript (ES6, ES7, ES8) 🚀
Stars: ✭ 42,981 (+87616.33%)
Mutual labels:  nest, nestjs
Schedule
Schedule module for Nest framework (node.js) ⏰
Stars: ✭ 137 (+179.59%)
Mutual labels:  nest, nestjs
Sequelize
Sequelize module for Nest framework (node.js) 🍈
Stars: ✭ 88 (+79.59%)
Mutual labels:  nest, nestjs
Simple Todos
A simple web application powered by Nuxt.js 💚 & Nest Framework 😻
Stars: ✭ 81 (+65.31%)
Mutual labels:  nest, nestjs
Nest Passport
Nest authentication example using passport strategies
Stars: ✭ 44 (-10.2%)
Mutual labels:  nest, nestjs
Nestjs Roles
Type safe roles guard and decorator made easy
Stars: ✭ 78 (+59.18%)
Mutual labels:  nest, nestjs
Serverless Core
Serverless Core module for Nest framework (node.js) 🦊
Stars: ✭ 154 (+214.29%)
Mutual labels:  nest, nestjs
MyAPI
A template to create awesome APIs easily ⚡️
Stars: ✭ 117 (+138.78%)
Mutual labels:  nest, nestjs

nest-ratelimiter

npm GitHub branch checks state Supported platforms: Express & Fastify

Snyk Vulnerabilities for npm package Dependencies status Dependabot Maintainability

The most flexible NestJS rate limiter based on Redis (rate limit against not only req path but req body to block distributed brute force attacks).

Install

npm i nest-ratelimiter ratelimiter @types/ratelimiter

If you want to use default response when reaching limit (text: "Rate limit exceeded, retry in human readable time value") also install ms.

npm i nest-ratelimiter ratelimiter @types/ratelimiter ms

Usage

Let's start with controllers. Controllers are the places where you set parameters for rate-limiter guard. You can set parameters for an entire controller or handler. Also, you can override the parameters of an entire controller by providing parameters for a specific handler. And finally, you can set several params for multi-checking.

import { RateLimiter, LimiterInfo } from 'nest-ratelimiter';

// Let's define several functions that returns the identifier
// to limit against.

// This is functions for limiting requests by IP
function getRequestIP(ctx: ExecutionContext) {
  const request = ctx.switchToHttp().getRequest();
  return request.ip;
}

// Also you can limit every path separately
function getRequestIPAndPath(ctx: ExecutionContext) {
  const request = ctx.switchToHttp().getRequest();
  return `${request.ip}:${request.path}`;
}

// For blocking brute force attacks on login
// you can return `login` value as identifier
function getRequestBodyLogin(ctx: ExecutionContext) {
  const request = ctx.switchToHttp().getRequest();
  return request.body.login;
}

// Now let's setup controller

@Controller('/')
// set params for entire controller
@RateLimiter({ getId: getRequestIP })
class TestController {
  // without providing params for specific handler
  // it will inherit params of entire controller
  @Get('some-api')
  someApi() {
    // ...
  }

  @Get('some-other-api')
  // override params for specific handler
  @RateLimiter({
    getId: getRequestIPAndPath,
    max: 10,
    duration: 10000,
  })
  someOtherApi() {
    // ...
  }

  @Get('one-more-api')
  // turn off rate limiter for specific handler
  @RateLimiter(false)
  oneMoreApi() {
    // ...
  }

  @Get('login')
  // override params for specific handler
  // by providing several params
  @RateLimiter(
    {
      getId: getRequestIPAndPath,
      max: 3,
      duration: 60 * 60 * 1000,
    },
    {
      getId: getRequestBodyLogin,
      max: 3,
      duration: 60 * 60 * 1000,
      // this is default `createErrorBody` function
      // but you can set your own
      createErrorBody: (limit: LimiterInfo) => {
        const delta = limit.reset * 1000 - Date.now();
        // ms is imported from `ms` module
        const readable = ms(delta, { long: true });
        return 'Rate limit exceeded, retry in ' + readable;
      },
    },
  )
  login(creds: CredsDto) {
    // ...
  }
}

Please, check out the docs of ratelimiter npm module for better understanding of @RateLimiter configuration.

Let's move to module registration. As nest-ratelimiter is using redis as data store you have to provide an instance of Redis client (redis or ioredis). As Redis client instantiation is out of scope of this package, you can find something that fit your needs on npm or create your own module for NestJS. Here we will show an example with nestjs-redis module:

import { RedisModule } from 'nestjs-redis';
import { RateLimiterModule, LimiterInfo } from 'nest-ratelimiter';

@Module({
  imports: [
    RateLimiterModule.forRoot({

      // The only required field is `db` (redis client), all the rest fields
      // will be used as defaults for `@RateLimiter(...)`
      db: require("redis").createClient()

    }),

    RateLimiterModule.forRootAsync({

      // 1 Register third-party module that provides `redis` or `ioredis` client
      imports: [
        RedisModule.register({
          host: process.env.REDIS_HOST,
          port: parseInt(process.env.REDIS_PORT),
          db: parseInt(process.env.REDIS_DB),
        }),
      ],

      // 2 And then inject redis client provider
      inject: [RedisService],

      // 3. build and return `RateLimiterModuleParams` from factory
      useFactory: async (redisService: RedisService) => {

        // You can set default fields for every @RateLimiter and then you don't
        // have to copy-paste your params on entire codebase.

        // IF YOU SET `getId` HERE, THEN ALL CONTROLLERS (EVEN THOSE WITHOUT
        // @RateLimiter GUARD) WILL USE THIS FUNCTION BY DEFAULT. IF IN THAT
        // CASE YOU NEED TO TURN OFF RATE LIMITER ON SOME SPECIFIC HANDLER OR
        // CONTROLLER JUST USE `@RateLimiter(false)`

        return {
          db: redisService.getClient(),
          max: 10,
          duration: 10000,
          getId: getRequestIPAndPath;
          createErrorBody: (limit: LimiterInfo) => ({
            error: {
              code: 'MY-RATE-LIMIT-ERROR-CODE',
              params: limit,
            },
          }),
        };
      },

    }),
  ],
  controllers: [TestController],
})
class TestModule {}

And the last thing to do is set up guard globally:

import { RATELIMITER_GUARD_TOKEN } from 'nest-ratelimiter';

const app = await NestFactory.create(AppModule);
app.useGlobalGuards(app.get(RATELIMITER_GUARD_TOKEN));

Comparison with others

This nest-ratelimiter is using TJ's ratelimiter package underhood, so it allows the creation of really flexible strategy for limiting not only per request path but per headers or body values and so on (see examples above). It stores data only in redis. If you need another store you can look at nestjs-rate-limiter, but it allows the use of strategies based on request path only. Also there is an example in official docs with setting up express-rate-limit middleware.

Migration

0.2.0

  • nestjs-redis was moved from dependencies, now you are free to use any redis module that fit your needs, but you have to set new field RateLimiterModuleParams.db that should be redis or ioredis instance.
  • ratelimiter (with @types/ratelimiter) was moved to peer dependencies. If you are using npm@7 it will install it automatically, either way you should install it manually.

Do you use this library?
Don't be shy to give it a star! ★

Also, if you are into NestJS ecosystem you may be interested in one of my other libs:

nestjs-pino

GitHub stars npm

Platform agnostic logger for NestJS based on pino with request context in every log


nestjs-session

GitHub stars npm

Idiomatic session module for NestJS. Built on top of express-session


nestjs-cookie-session

GitHub stars npm

Idiomatic cookie session module for NestJS. Built on top of cookie-session


nestjs-roles

GitHub stars npm

Type safe roles guard and decorator made easy


nestjs-injectable

GitHub stars npm

@Injectable() on steroids that simplifies work with inversion of control in your hexagonal architecture


nest-ratelimiter

GitHub stars npm

Distributed consistent flexible NestJS rate limiter based on Redis


create-nestjs-middleware-module

GitHub stars npm

Create simple idiomatic NestJS module based on Express/Fastify middleware in just a few lines of code with routing out of the box


nestjs-configure-after

GitHub stars npm

Declarative configuration of NestJS middleware order

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].