Skip to content
Rate limit made simple, easy, async.
JavaScript
Branch: master
Clone or download
Latest commit 987bb14 Aug 9, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src refactor: extract into a function Apr 20, 2019
test refactor: simplify code Mar 27, 2019
.bumpedrc First commit Jun 17, 2018
.editorconfig First commit Jun 17, 2018
.gitattributes First commit Jun 17, 2018
.gitignore build: automate workflow Dec 17, 2018
.npmrc First commit Jun 17, 2018
.travis.yml
CHANGELOG.md chore(release): 1.2.7 Jul 11, 2019
LICENSE First commit Jun 17, 2018
README.md Update README.md Jul 11, 2019
index.d.ts fix(typescript-declarations): missing decrease param at GetOptions in… Apr 4, 2019
package.json build: update meta Aug 9, 2019

README.md

async-ratelimiter

Last version Build Status Coverage Status Dependency status Dev Dependencies Status NPM Status

Rate limit made simple, easy, async. Based on ratelimiter.

NOTE: It requires Redis 2.6.12+.

Install

$ npm install async-ratelimiter --save

Usage

A simple middleware implementation for whatever HTTP server:

'use strict'

const RateLimiter = require('async-ratelimiter')
const { getClientIp } = require('request-ip')
const Redis = require('ioredis')

const rateLimiter = new RateLimiter({
  db: new Redis()
})

const apiQuota = async (req, res, next) => {
  const clientIp = getClientIp(req)
  const limit = await rateLimiter.get({ id: req.clientIp })

  if (!res.finished && !res.headersSent) {
    res.setHeader('X-Rate-Limit-Limit', limit.total)
    res.setHeader('X-Rate-Limit-Remaining', Math.max(0, limit.remaining - 1))
    res.setHeader('X-Rate-Limit-Reset', limit.reset)
  }

  return !limit.remaining
    ? sendFail({ req,
      res,
      code: HTTPStatus.TOO_MANY_REQUESTS,
      message: MESSAGES.RATE_LIMIT_EXCEDEED()
    })
    : next(req, res)
}

API

constructor(options)

It creates an rate limiter instance.

options

db

Required
Type: object

The redis connection instance.

max

Type: number
Default: 2500

The maximum number of requests within duration.

duration

Type: number
Default: 3600000

How long keep records of requests in milliseconds.

namespace

Type: string
Default: 'limit'

The prefix used for compound the key.

id

Type: string

The identifier to limit against (typically a user id).

You can pass this value using when you use .get method as well.

.get(options)

Given an id, returns a Promise with the status of the limit with the following structure:

  • total: max value.
  • remaining: number of calls left in current duration without decreasing current get.
  • reset: time since epoch in seconds that the rate limiting period will end (or already ended).

options

id

Type: string Default: this.id

The identifier to limit against (typically a user id).

max

Type: number
Default: this.max

The maximum number of requests within duration. If provided, it overrides the default max value. This is useful for custom limits that differ between IDs.

duration

Type: number
Default: this.max

How long keep records of requests in milliseconds. If provided, it overrides the default duration value.

decrease

Type: boolean
Default: true

When set to false, the remaining number of calls is not decreased.

In some scenarios it might be useful to be able to read the current "remaining" value for a limiter.

const loginHandler = async (req, res, next) => {
  const clientIp = getClientIp(req)
  const limit = await rateLimiter.get({ id: clientIp, decrease: false })

  if (!limit.remaining) return sendError(req, res, 429)

  try {
    await doLogin(req)
  } catch (err) {
    if (err) {
      await rateLimiter.get({ id: req.clientIp })
      return sendError(req, res, 401)
    }
  }

  next(req, res)
}

In this example, new login attempts are rejected when more at least 10 unsuccessful login attempts happened in the last 60 seconds.

Related

  • express-slow-down – Slow down repeated requests; use as an alternative (or addition) to express-rate-limit.

License

async-ratelimiter © microlink.io, released under the MIT License.
Authored and maintained by microlink.io with help from contributors.

microlink.io · GitHub microlink.io · Twitter @microlinkhq

You can’t perform that action at this time.