Skip to content

Rate limit with Redis

Simon Bonnard edited this page Sep 14, 2013 · 4 revisions

Use Redis Throttle to set a daily rate limit to your Rails app

Install

Update your gem file and run bundle

gem 'redis-throttle', git: 'git@github.com:andreareginato/redis-throttle.git'

Create your own Redis Throttle

Subclass Rack::RedisThrottle::Daily and create your own rules. In this case we set the user id as the client identifier and we dynamically set the rate limit per user through the user#rate_limit field.

# /lib/middlewares/daily_rate_limit
require 'rack/redis_throttle'

class DailyRateLimit < Rack::RedisThrottle::Daily

  def call(env)
    @user_rate_limit = user_rate_limit(env)
    super
  end

  def client_identifier(request)
    @user_rate_limit.respond_to?(:_id) ? @user_rate_limit._id : 'user-unknown'
  end

  def max_per_window(request)
    @user_rate_limit.respond_to?(:rate_limit) ? @user_rate_limit.rate_limit : 1000
  end

  # Rate limit only requests sending the access token
  def need_protection?(request)
    request.env.has_key?('HTTP_AUTHORIZATION')
  end

  private

  def user_rate_limit(env)
    request      = Rack::Request.new(env)
    token        = request.env['HTTP_AUTHORIZATION'].split(' ')[-1]
    access_token = Doorkeeper::AccessToken.where(token: token).first
    access_token ? User.find(access_token.resource_owner_id) : nil
  end
end

Configuration

# config/application.rb
module App
  class Application < Rails::Application
  
    # Puts your rate limit middleware as high as you can in your middleware stack
    config.middleware.insert_after Rack::Lock, 'DailyRateLimit'

Rate limit headers

Rack::RedisThrottle automatically sets two rate limits headers to let the client know the max number of requests and the one availables.

HTTP/1.1 200 OK
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999

When you exceed the API calls limit your request is forbidden.

HTTP/1.1 403 Forbidden
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 0

Testing your apps

While testing your Rack app Mock the redis connection by requiring this file

  # Rate limit fake redis connection
  require 'rack/redis_throttle/testing/connection'
Clone this wiki locally