Giter Site home page Giter Site logo

fastify-rate-limit's Introduction

fastify-rate-limit

Greenkeeper badge js-standard-style Build Status

A low overhead rate limiter for your routes. Supports Fastify 2.x versions.

Please refer to this branch and related versions for Fastify 1.x compatibility.

Install

npm i fastify-rate-limit

Usage

Register the plugin pass to it some custom option.
This plugin will add an onRequest hook to check if the clients (based on their ip) has done too many request in the given timeWindow.

const fastify = require('fastify')()

fastify.register(require('fastify-rate-limit'), {
  max: 100,
  timeWindow: '1 minute'
})

fastify.get('/', (req, reply) => {
  reply.send({ hello: 'world' })
})

fastify.listen(3000, err => {
  if (err) throw err
  console.log('Server listening at http://localhost:3000')
})

In case a client reaches the maximum number of allowed requests, a standard Fastify error will be returned to the user with the status code setted to 429:

{
  statusCode: 429,
  error: 'Too Many Requests',
  message: 'Rate limit exceeded, retry in 1 minute'
}

Options

You can pass the following options during the plugin registration:

fastify.register(require('fastify-rate-limit'), {
  global : false, // default true
  max: 3, // default 1000
  timeWindow: 5000, // default 1000 * 60
  cache: 10000, // default 5000
  whitelist: ['127.0.0.1'], // default []
  redis: new Redis({ host: '127.0.0.1' }), // default null
  skipOnError: true, // default false
  keyGenerator: function(req) { /* ... */ }, // default (req) => req.raw.ip
})
  • global : indicates if the plugin should apply the rate limit setting to all routes within the encapsulation scope
  • max: is the maximum number of requests a single client can perform inside a timeWindow.
  • timeWindow: the duration of the time window. It can be expressed in milliseconds or as a string (in the ms format)
  • cache: this plugin internally uses a lru cache to handle the clients, you can change the size of the cache with this option
  • whitelist: array of string of ips to exclude from rate limiting
  • redis: by default this plugins uses an in-memory store, which is fast but if you application works on more than one server it is useless, since the data is store locally.
    You can pass a Redis client here and magically the issue is solved. To achieve the maximum speed, this plugins requires the use of ioredis
  • skipOnError: if true it will skip errors generated by the storage (eg, redis not reachable).
  • keyGenerator: a function to generate a unique identifier for each incoming request. Defaults to (req) => req.ip, the IP is resolved by fastify using req.connection.remoteAddress or req.headers['x-forwarded-for'] if trustProxy option is enabled. Use it if you want to override this behavior

keyGenerator example usage:

fastify.register(require('fastify-rate-limit'), {
  /* ... */
  keyGenerator: function(req) {
    return req.headers['x-real-ip'] // nginx
    || req.headers['x-client-ip'] // apache
    || req.headers['x-forwarded-for'] // use this only if you trust the header
    || req.session.username // you can limit based on any session value
    || req.raw.ip // fallback to default
})

Options on the endpoint itself

Rate limiting can be configured also for some routes, applying the configuration independently.

For example the whitelist if configured:

  • on the plugin registration will affect all endpoints within the encapsulation scope
  • on the route declaration will affect only the targeted endpoint

The global whitelist is configured when registering it with fastify.register(...).

The endpoint whitelist is set on the endpoint directly with the { config : { rateLimit : { whitelist : [] } } } object.

ACL checking is performed based on the value of the key from the keyGenerator.

In this example we are checking the IP address, but it could be a whitelist of specific user identifiers (like JWT or tokens):

const fastify = require('fastify')()

fastify.register(require('fastify-rate-limit'),
  {
    global : false, // don't apply these settings to all the routes of the context
    max: 3000, // default global max rate limit
    whitelist: ['192.168.0.10'], // global whitelist access. 
    redis: redis, // custom connection to redis
  })

// add a limited route with this configuration plus the global one
fastify.get('/', {
  config: {
    rateLimit: {
      max: 3,
      timeWindow: '1 minute'
    }
  }
}, (req, reply) => {
  reply.send({ hello: 'from ... root' })
})

// add a limited route with this configuration plus the global one
fastify.get('/private', {
  config: {
    rateLimit: {
      max: 3,
      timeWindow: '1 minute'
    }
  }
}, (req, reply) => {
  reply.send({ hello: 'from ... private' })
})

// this route doesn't have any rate limit
fastify.get('/public', (req, reply) => {
  reply.send({ hello: 'from ... public' })
})

// add a limited route with this configuration plus the global one
fastify.get('/public/sub-rated-1', {
  config: {
    rateLimit: {
      timeWindow: '1 minute',
      whitelist: ['127.0.0.1'],
      onExceeding: function (req) {
        console.log('callback on exceededing ... executed before response to client')
      },
      onExceeded: function (req) {
        console.log('callback on exceeded ... to black ip in security group for example, req is give as argument')
      }
    }
  }
}, (req, reply) => {
  reply.send({ hello: 'from sub-rated-1 ... using default max value ... ' })
})

In the route creation you can override the same settings of the plugin registration plus the additionals options:

  • onExceeding : callback that will be executed each time a request is made to a route that is rate limited
  • onExceeded : callback that will be executed when a user reached the maximum number of tries. Can be useful to blacklist clients

License

MIT

Copyright © 2018 Tomas Della Vedova

fastify-rate-limit's People

Contributors

delvedor avatar cemremengu avatar mcollina avatar greenkeeper[bot] avatar fox1t avatar eomm avatar karlos1337 avatar pc-jedi avatar

Stargazers

Roman avatar

Watchers

James Cloos 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.