Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throttling POST requests in rails application

I'm using rack-throttle as a rate-limiting engine in my rails 3 application. I've created my own class based on the Rack::Throttle::Interval to define custom rate limiting logic. I'm checking if the request is made to exact controller and exact action. This works fine if I make GET request. However if i send POST request i get some problems.

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

Here are my controller actions

def question
  #user is redirected here
end

def check_answer
  #some logic to check answer
  redirect_to question_path
end

My routes

get "questions" => "application#question", :as => "question"
post "check_answer" => "application#check_answer", :as => "check_answer"

EDIT:

The problem is that POST requests are coming to application so that method allowed? is called. But when i call Rails.application.routes.recognize_path i get a Route set not finalized exception. How can i prevent a user from sending a lot of post requests on the exact action of the exact controller with the help of rack-throttle

The middleware is added in application.rb

class Application < Rails::Application
  #Set up rate limiting
  config.require "ip_limiter"
  config.require "ip_user_agent_limiter"
  config.middleware.use IpLimiter, :min => 0.2
  config.middleware.use IpUserAgentLimiter, :min => 2
end

Both IpLimiter and IpUserAgentLimiter are derived from custom limiter

like image 388
roman Avatar asked Nov 05 '22 03:11

roman


1 Answers

After reading the code of Rails.application.routes.recognize_path ( http://apidock.com/rails/ActionDispatch/Routing/RouteSet/recognize_path ), this methode get a second args where you can pass the METHOD.

Try with :

path_info = Rails.application.routes.recognize_path(request.url, {:method => request.request_method}) rescue path_info = {} 

After all method can works I suppose.

like image 99
shingara Avatar answered Nov 15 '22 05:11

shingara