在特定的Rails路由上触发Rack中间件

Cev*_*Cev 11 rack ruby-on-rails

是否可以仅在特定的Rails路由上触发Rack中间件?

例如,假设我想仅在api命名空间上运行速率限制器中间件.

namespace :api do
  resources :users
end
Run Code Online (Sandbox Code Playgroud)

小智 14

我使用Rack :: Throttle在速率限制方面取得了很大的成功.子类化其中一个内置的油门类并重载该allowed?方法.您的自定义逻辑可以检查正在访问哪个控制器并根据需要应用速率限制.

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
Run Code Online (Sandbox Code Playgroud)


Edu*_*rdo 5

除了Ian的答案,要设置ApiThrottle,你必须:

# 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
Run Code Online (Sandbox Code Playgroud)

要补充的一件重要事情是,对我而言,不仅仅是作为path_info[:controller]而来.当然,这是由命名空间配置引起的.因此,在设置节流器时要小心."api/v1/cities""api"