README in rack-throttle-0.1.0 vs README in rack-throttle-0.2.0
- old
+ new
@@ -1,15 +1,30 @@
-HTTP Request Rate Limiter for Rack
-==================================
+HTTP Request Rate Limiter for Rack Applications
+===============================================
This is [Rack][] middleware that provides logic for rate-limiting incoming
-HTTP requests to your Rack application. You can use `Rack::Throttle` with
-any Ruby web framework based on Rack, including with Ruby on Rails 3.0 and
-with Sinatra.
+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.
* <http://github.com/datagraph/rack-throttle>
+Features
+--------
+
+* Throttles a Rack application by enforcing a minimum interval (by default,
+ 1 second) between subsequent HTTP requests from a particular client.
+* 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).
+
Examples
--------
### Adding throttling to a Rackup application
@@ -21,14 +36,66 @@
### Enforcing a 3-second interval between requests
use Rack::Throttle::Interval, :min => 3.0
+### Using GDBM to store rate-limiting counters
+
+ require 'gdbm'
+ use Rack::Throttle::Interval, :cache => GDBM.new('tmp/throttle.db')
+
### Using Memcached to store rate-limiting counters
+ require 'memcached'
use Rack::Throttle::Interval, :cache => Memcached.new, :key_prefix => :throttle
+### Using Redis to store rate-limiting counters
+
+ require 'redis'
+ use Rack::Throttle::Interval, :cache => Redis.new, :key_prefix => :throttle
+
+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 `Rack::Throttle::Interval` and override the
+`#client_identifier` method.
+
+HTTP Response Codes and Headers
+-------------------------------
+
+### 403 Forbidden (Rate Limit Exceeded)
+
+When a client exceeds their rate limit, `Rack::Throttle` by default returns
+a "403 Forbidden" response with an associated "Rate Limit Exceeded" message
+in the response body.
+
+An HTTP 403 response means that the server understood the request, but is
+refusing to respond to it and an accompanying message will explain why.
+This indicates an error on the client's part in exceeding the rate limits
+outlined in the acceptable use policy for the site, service, or API.
+
+### 503 Service Unavailable (Rate Limit Exceeded)
+
+However, there is an unfortunately widespread practice of instead returning
+a "503 Service Unavailable" response when a client exceeds the set rate
+limits. This is actually technically incorrect because it indicates an
+error on the server's part, which is certainly not the case with rate
+limiting - it was the client that committed the oops, not the server.
+
+An HTTP 503 response would be correct in situations where the server was
+genuinely overloaded and couldn't handle more requests, but for rate
+limiting an HTTP 403 response is more appropriate. Nonetheless, if you think
+otherwise, `Rack::Throttle` does allow you to override the returned HTTP
+status code by passing in a `:code => 503` option when constructing a
+`Rack::Throttle::Limiter` instance.
+
Documentation
-------------
<http://datagraph.rubyforge.org/rack-throttle/>
@@ -71,6 +138,13 @@
-------
`Rack::Throttle` is free and unencumbered public domain software. For more
information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
-[Rack]: http://rack.rubyforge.org/
+[Rack]: http://rack.rubyforge.org/
+[gdbm]: http://ruby-doc.org/stdlib/libdoc/gdbm/rdoc/classes/GDBM.html
+[memcached]: http://rubygems.org/gems/memcached
+[memcache-client]: http://rubygems.org/gems/memcache-client
+[memcache]: http://rubygems.org/gems/memcache
+[redis]: http://rubygems.org/gems/redis
+[Heroku]: http://heroku.com/
+[Heroku memcache]: http://docs.heroku.com/memcache