Trigger Rack middleware on specific Rails routes

六月ゝ 毕业季﹏ 提交于 2019-11-30 08:24:58

问题


Is it possible to trigger Rack middleware only on specific Rails routes?

For example, let's say I wanted to run a rate limiter middleware only on the api namespace.

namespace :api do
  resources :users
end

回答1:


I've had good success with Rack::Throttle for rate limiting. Subclass one of the built-in throttle classes and overload the allowed? method. Your custom logic can check which controller is being accessed and apply the rate limit as needed.

class ApiThrottle < Rack::Throttle::Hourly
  ##
  # Returns `false` if the rate limit has been exceeded for the given
  # `request`, or `true` otherwise.
  #
  # Rate limits are only imposed on the "api" controller
  #
  # @param  [Rack::Request] request
  # @return [Boolean]
  def allowed?(request)
    path_info = (Rails.application.routes.recognize_path request.url rescue {}) || {} 

    # Check if this route should be rate-limited
    if path_info[:controller] == "api"
      super
    else
      # other routes are not throttled, so we allow them
      true
    end
  end
end



回答2:


Adding to Ian's answer, to setup up the ApiThrottle you have to:

# application.rb
require 'rack/throttle'
class Application < Rails::Application
  ...
  config.require "api_throttle"
  # max 100 requests per hour per ip
  config.middleware.use ApiThrottle, :max => 100
  ...
end

# /lib/api_throttle.rb
# Ian's code here

One important thing to add is that, for me, the path_info[:controller] came as "api/v1/cities" and not only as "api". Of course, that is due to the namespace configuration. Therefore, take care when setting up the throttler.




回答3:


You can also (now) use a Rails Engine to create an isolated set of routes that adds additional middleware to the stack for its mounted routes.

See https://stackoverflow.com/a/41515577/79079

(Unfortunately I found this question while looking to see if there was any simpler way to do it. Writing a custom middleware for every middleware that I wanted to add seems even more round-about than using a Rails::Engine)



来源:https://stackoverflow.com/questions/12679644/trigger-rack-middleware-on-specific-rails-routes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!