[英]Trigger Rack middleware on specific Rails routes
Is it possible to trigger Rack middleware only on specific Rails routes? 是否可以仅在特定的Rails路由上触发Rack中间件?
For example, let's say I wanted to run a rate limiter middleware only on the api namespace. 例如,假设我只想在api名称空间上运行限速器中间件。
namespace :api do
resources :users
end
I've had good success with Rack::Throttle for rate limiting. 我使用Rack :: Throttle进行了成功的速率限制。 Subclass one of the built-in throttle classes and overload the allowed?
子类化内置节气门类之一,并allowed?
重载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
Adding to Ian's answer, to setup up the ApiThrottle you have to: 添加到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
One important thing to add is that, for me, the path_info[:controller]
came as "api/v1/cities"
and not only as "api"
. 要补充的一件事是,对我而言, path_info[:controller]
以"api/v1/cities"
,而不仅仅是以"api"
。 Of course, that is due to the namespace configuration. 当然,这是由于名称空间配置所致。 Therefore, take care when setting up the throttler. 因此,在安装节流阀时要小心。
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. 您还可以(现在)使用Rails Engine创建一组隔离的路由,从而为堆栈中已安装的路由添加其他中间件。
See https://stackoverflow.com/a/41515577/79079 参见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) (不幸的是,我在寻找是否有更简单的方法时发现了这个问题。为我想添加的每个中间件编写一个定制的中间件似乎比使用Rails :: Engine更复杂。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.