npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@alkihis/express-rate-limit

v5.1.6

Published

Basic IP rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.

Downloads

18

Readme

Express Rate Limit

Build Status NPM version Dependency Status Development Dependency Status

Basic rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.

Plays nice with express-slow-down.

Note: this module does not share state with other processes/servers by default. If you need a more robust solution, I recommend using an external store:

Stores

Alternate Rate-limiters

This module was designed to only handle the basics and didn't even support external stores initially. These other options all are excellent pieces of software and may be more appropriate for some situations:

Install

$ npm install --save express-rate-limit

Usage

For an API-only server where the rate-limiter should be applied to all requests:

const rateLimit = require("express-rate-limit");

// Enable if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB, Nginx, etc)
// see https://expressjs.com/en/guide/behind-proxies.html
// app.set('trust proxy', 1);

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100 // limit each IP to 100 requests per windowMs
});

//  apply to all requests
app.use(limiter);

For a "regular" web server (e.g. anything that uses express.static()), where the rate-limiter should only apply to certain requests:

const rateLimit = require("express-rate-limit");

// Enable if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB, Nginx, etc)
// see https://expressjs.com/en/guide/behind-proxies.html
// app.set('trust proxy', 1);

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100
});

// only apply to requests that begin with /api/
app.use("/api/", apiLimiter);

Create multiple instances to apply different rules to different routes:

const rateLimit = require("express-rate-limit");

// Enable if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB, Nginx, etc)
// see https://expressjs.com/en/guide/behind-proxies.html
// app.set('trust proxy', 1);

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100
});
app.use("/api/", apiLimiter);

const createAccountLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour window
  max: 5, // start blocking after 5 requests
  message:
    "Too many accounts created from this IP, please try again after an hour"
});
app.post("/create-account", createAccountLimiter, function(req, res) {
  //...
});

Note: most stores will require additional configuration, such as custom prefixes, when using multiple instances. The default built-in memory store is an exception to this rule.

Request API

A req.rateLimit property is added to all requests with the limit, current, and remaining number of requests and, if the store provides it, a resetTime Date object. These may be used in your application code to take additional actions or inform the user of their status.

Configuration options

max

Max number of connections during windowMs milliseconds before sending a 429 response.

May be a number, or a function that returns a number or a promise. If max is a function, it will be called with req and res params.

Defaults to 5. Set to 0 to disable.

windowMs

Timeframe for which requests are checked/remembered. Also used in the Retry-After header when the limit is reached.

Note: with non-default stores, you may need to configure this value twice, once here and once on the store. In some cases the units also differ (e.g. seconds vs miliseconds)

Defaults to 60000 (1 minute).

message

Error message sent to user when max is exceeded.

May be a String, JSON object, or any other value that Express's res.send supports.

Defaults to 'Too many requests, please try again later.'

statusCode

HTTP status code returned when max is exceeded.

Defaults to 429.

headers

Enable headers for request limit (X-RateLimit-Limit) and current usage (X-RateLimit-Remaining) on all responses and time to wait before retrying (Retry-After) when max is exceeded.

Defaults to true. Behavior may change in the next major release.

draft_polli_ratelimit_headers

Enable headers conforming to the ratelimit standardization proposal: RateLimit-Limit, RateLimit-Remaining, and, if the store supports it, RateLimit-Reset. May be used in conjunction with, or instead of the headers option.

Defaults to false. Behavior and name will likely change in future releases.

keyGenerator

Function used to generate keys.

Defaults to req.ip:

function (req /*, res*/) {
    return req.ip;
}

handler

The function to handle requests once the max limit is exceeded. It receives the request and the response objects. The "next" param is available if you need to pass to the next middleware.

Thereq.rateLimit object has limit, current, and remaining number of requests and, if the store provides it, a resetTime Date object.

Defaults to:

function (req, res, /*next*/) {
    res.status(options.statusCode).send(options.message);
}

onLimitReached

Function that is called the first time a user hits the rate limit within a given window.

Thereq.rateLimit object has limit, current, and remaining number of requests and, if the store provides it, a resetTime Date object.

Default is an empty function:

function (req, res, options) {
  /* empty */
}

skipFailedRequests

When set to true, failed requests won't be counted. Request considered failed when:

  • response status >= 400
  • requests that were cancelled before last chunk of data was sent (response close event triggered)
  • response error event was triggrered by response

(Technically they are counted and then un-counted, so a large number of slow requests all at once could still trigger a rate-limit. This may be fixed in a future release.)

Defaults to false.

skipSuccessfulRequests

When set to true successful requests (response status < 400) won't be counted. (Technically they are counted and then un-counted, so a large number of slow requests all at once could still trigger a rate-limit. This may be fixed in a future release.)

Defaults to false.

skip

Function used to skip (whitelist) requests. Returning true from the function will skip limiting for that request.

Defaults to always false (count all requests):

function (/*req, res*/) {
    return false;
}

store

The storage to use when persisting rate limit attempts.

By default, the MemoryStore is used.

Available data stores are:

You may also create your own store. It must implement the following in order to function:

function SomeStore() {
  /**
   * Increments the value in the underlying store for the given key.
   * @method function
   * @param {string} key - The key to use as the unique identifier passed
   *                     down from RateLimit.
   * @param {Function} cb - The callback issued when the underlying
   *                                store is finished.
   *
   * The callback should be called with three values:
   *  - error (usually null)
   *  - hitCount for this IP
   *  - resetTime - JS Date object (optional, but necessary for X-RateLimit-Reset header)
   */
  this.incr = function(key, cb) {
    // increment storage
    cb(null, hits, resetTime);
  };

  /**
   * Decrements the value in the underlying store for the given key. Used only when skipFailedRequests is true
   * @method function
   * @param {string} key - The key to use as the unique identifier passed
   *                     down from RateLimit.
   */
  this.decrement = function(key) {
    // decrement storage
  };

  /**
   * Resets a value with the given key.
   * @method function
   * @param  {[type]} key - The key to reset
   */
  this.resetKey = function(key) {
    // remove key from storage or reset it to 0
  };
}

Instance API

instance.resetKey(key)

Resets the rate limiting for a given key. (Allow users to complete a captcha or whatever to reset their rate limit, then call this method.)

Summary of breaking changes:

v5 changes

  • Removed index.d.ts. (See #138)

v4 Changes

  • Express Rate Limit no longer modifies the passed-in options object, it instead makes a clone of it.

v3 Changes

  • Removed delayAfter and delayMs options; they were moved to a new module: express-slow-down.
  • Simplified the default handler function so that it no longer changes the response format. Now uses res.send.
  • onLimitReached now only triggers once for a given ip and window. only handle is called for every blocked request.

v2 Changes

v2 uses a less precise but less resource intensive method of tracking hits from a given IP. v2 also adds the limiter.resetKey() API and removes the global: true option.

License

MIT © Nathan Friedly