-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Update your gem file and run bundle
gem 'redis-throttle', git: 'git@github.com:andreareginato/redis-throttle.git'
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
# 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'
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
While testing your Rack app Mock the redis connection by requiring this file
# Rate limit fake redis connection
require 'rack/redis_throttle/testing/connection'