繁体   English   中英

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

[英]Trigger Rack middleware on specific Rails routes

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

例如,假设我只想在api名称空间上运行限速器中间件。

namespace :api do
  resources :users
end

我使用Rack :: Throttle进行了成功的速率限制。 子类化内置节气门类之一,并allowed?重载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

添加到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

要补充的一件事是,对我而言, path_info[:controller]"api/v1/cities" ,而不仅仅是以"api" 当然,这是由于名称空间配置所致。 因此,在安装节流阀时要小心。

您还可以(现在)使用Rails Engine创建一组隔离的路由,从而为堆栈中已安装的路由添加其他中间件。

参见https://stackoverflow.com/a/41515577/79079

(不幸的是,我在寻找是否有更简单的方法时发现了这个问题。为我想添加的每个中间件编写一个定制的中间件似乎比使用Rails :: Engine更复杂。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM