roman
roman

Reputation: 5210

Rate-limiting for rails controllers

I'm searching rate-limiting engine for my rails 3 application. I've found some but that's not what i need. I 've found rack-throttle gem and curbit gem. It seems that rack-throttle works for each request to rails application but i need to limit requests only to one action. Curbit was last updated two years ago. Can anyone tell me about any other rate-limiting engines that i can use? Note that it should work with caching.

Upvotes: 7

Views: 8505

Answers (2)

roman
roman

Reputation: 5210

Well, finally rack throttle is a good solution.

You can do it the following way. You need to define your custom limiter. It can be based on either of the following limiters

Rack::Throttle::Limiter
Rack::Throttle::Interval
Rack::Throttle::Hourly
Rack::Throttle::Daily

Everything you need to do is derive from one of the above classes to define custom logic. For example:

class CustomLimiter < Rack::Throttle::Interval
  def allowed?(request)
  #custom logic here
  end
end

You should put this file in the RAILS_ROOT/lib path. Then in the application.rb file you should specify what class to use as a limiter. For example if you want to apply limiter only to one action you can do it the following way:

#lib/custom_limiter.rb
class CustomLimiter < Rack::Throttle::Interval
  def allowed?(request)
    path_info = Rails.application.routes.recognize_path request.url rescue {}
    if path_info[:controller] == "application" and path_info[:action] == "check_answer"
      super
    else 
      true
    end
  end
end

#config/application.rb
class Application < Rails::Application
  ... 
  #Set up rate limiting
  config.require "custom_limiter"
  config.middleware.use CustomLimiter, :min => 0.2
  ...
end

You may need to take this into consideration

Hope this will be useful

UPD:

you may want to check out another solution: rack-attack

Upvotes: 13

Reactormonk
Reactormonk

Reputation: 21730

rack-throttle does what you want. Subclass Limiter and define your own #allowed? method. Simply return true if the request isn't the action you want the limit and don't count it towards the limit. Take a look at daily.rb. Redefine #cache_set so it doesn't save those that don't match the route you want to limit.

Upvotes: 2

Related Questions