HTTP Request Rate Limiter for Rack Applications

This is [Rack][] middleware that provides logic for rate-limiting incoming HTTP requests to Rack applications. You can use ‘Rack::Throttle` with any Ruby web framework based on Rack, including with Ruby on Rails 3.0 and with Sinatra.

Features


  • Throttles a Rack application by enforcing a minimum time interval between subsequent HTTP requests from a particular client, as well as by defining a maximum number of allowed HTTP requests per a given time period (per minute, hourly, or daily).

  • Compatible with any Rack application and any Rack-based framework.

  • Stores rate-limiting counters in any key/value store implementation that responds to ‘#[]`/`#[]=` (like Ruby’s hashes) or to ‘#get`/`#set` (like memcached or Redis).

  • Compatible with the [gdbm][] binding included in Ruby’s standard library.

  • Compatible with the [memcached][], [memcache-client][], [memcache][] and

    redis][

    gems.

  • Compatible with [Heroku][]‘s [memcached add-on][Heroku memcache] (currently available as a free beta service).

  • Compatible with Ruby 1.8.7 & 1.9

Examples


### Adding throttling to a Rails 3.x application

# config/application.rb
require 'rack/throttle'

class Application < Rails::Application
  config.middleware.use Rack::Throttle::Interval
end

### Adding throttling to a Sinatra application

#!/usr/bin/env ruby -rubygems
require 'sinatra'
require 'rack/throttle'

use Rack::Throttle::Interval

get('/hello') { "Hello, world!\n" }

### Adding throttling to a Rackup application

#!/usr/bin/env rackup
require 'rack/throttle'

use Rack::Throttle::Interval

run lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, world!\n"] }

### Enforcing a minimum 3-second interval between requests

use Rack::Throttle::Interval, :min => 3.0

### Allowing a maximum of 60 requests per minute

use Rack::Throttle::Minute,   :max => 60

### Allowing a maximum of 100 requests per hour

use Rack::Throttle::Hourly,   :max => 100

### Allowing a maximum of 1,000 requests per day

use Rack::Throttle::Daily,    :max => 1000

### Combining various throttling constraints into one overall policy

use Rack::Throttle::Daily,    :max => 1000  # requests
use Rack::Throttle::Hourly,   :max => 100   # requests
use Rack::Throttle::Hourly,   :max => 60    # requests
use Rack::Throttle::Interval, :min => 3.0   # seconds

### Storing the rate-limiting counters in a GDBM database

require 'gdbm'

use Rack::Throttle::Interval, :cache => GDBM.new('tmp/throttle.db')

### Storing the rate-limiting counters on a Memcached server

require 'memcached'

use Rack::Throttle::Interval, :cache => Memcached.new, :key_prefix => :throttle

### Storing the rate-limiting counters on a Redis server

require 'redis'

use Rack::Throttle::Interval, :cache => Redis.new, :key_prefix => :throttle

Throttling Strategies


‘Rack::Throttle` supports three built-in throttling strategies:

  • ‘Rack::Throttle::Interval`: Throttles the application by enforcing a minimum interval (by default, 1 second) between subsequent HTTP requests.

  • ‘Rack::Throttle::Minute`: Throttles the application by defining a maximum number of allowed HTTP requests per minute (by default, 60 requests per minute, which works out to an average of 1 request per second).

  • ‘Rack::Throttle::Hourly`: Throttles the application by defining a maximum number of allowed HTTP requests per hour (by default, 3,600 requests per 60 minutes, which works out to an average of 1 request per second).

  • ‘Rack::Throttle::Daily`: Throttles the application by defining a maximum number of allowed HTTP requests per day (by default, 86,400 requests per 24 hours, which works out to an average of 1 request per second).

You can fully customize the implementation details of any of these strategies by simply subclassing one of the aforementioned default implementations. And, of course, should your application-specific requirements be significantly more complex than what we’ve provided for, you can also define entirely new kinds of throttling strategies by subclassing the ‘Rack::Throttle::Limiter` base class directly.

HTTP Client Identification


The rate-limiting counters stored and maintained by ‘Rack::Throttle` are keyed to unique HTTP clients.

By default, HTTP clients are uniquely identified by their IP address as returned by ‘Rack::Request#ip`. If you wish to instead use a more granular, application-specific identifier such as a session key or a user account name, you need only subclass a throttling strategy implementation and override the `#client_identifier` method.

HTTP Response Codes and Headers


### 429 Too Many Requests In the past various status codes has been used to indicate over-use.

In 2012, the IETF standardized on a new response status 429 (Too Many Requests) [RFC6585].

When a client exceeds their rate limit, ‘Rack::Throttle` by default returns a 429 (Too Many Requests) header with an associated “Rate Limit Exceeded” message in the response body.

The status code can be overridden by passing in ‘:code => 403` option when constructing a `Rack::Throttle::Limiter` instance.

Documentation


<datagraph.rubyforge.org/rack-throttle/>

Dependencies


Installation


The recommended installation method is via [RubyGems](rubygems.org/). To install the latest official release of the gem, do:

% [sudo] gem install rack-throttle

Download


To get a local working copy of the development repository, do:

% git clone git://github.com/datagraph/rack-throttle.git

Alternatively, you can download the latest development version as a tarball as follows:

% wget http://github.com/datagraph/rack-throttle/tarball/master

Authors


License


‘Rack::Throttle` is free and unencumbered public domain software. For more information, see <unlicense.org/> or the accompanying UNLICENSE file.

[Rack]: rack.rubyforge.org/ [gdbm]: ruby-doc.org/stdlib/libdoc/gdbm/rdoc/classes/GDBM.html [memcached]: rubygems.org/gems/memcached [memcache-client]: rubygems.org/gems/memcache-client [memcache]: rubygems.org/gems/memcache [redis]: rubygems.org/gems/redis [Heroku]: heroku.com/ [Heroku memcache]: docs.heroku.com/memcache [RFC6585]: tools.ietf.org/html/rfc6585