【发布时间】:2017-07-30 05:23:46
【问题描述】:
Rails 版本:'~> 4.2.7.1'
大礼包版本:'3.1.1'
TlDr:
如何在 Rails 4 应用程序的中间件中获取路由为 /api/products/:id 或控制器和该路由的操作。
详情:
我在我的 rails 应用程序中添加了一个类似于 gem scout_statsd_rack 的中间件。这会将以下 middleware 添加到 rails 应用程序以通过 statsd 发送指标:
def call(env)
(status, headers, body), response_time = call_with_timing(env)
statsd.timing("#{env['REQUEST_PATH']}.response", response_time)
statsd.increment("#{env['REQUEST_PATH']}.response_codes.#{status.to_s.gsub(/\d{2}$/,'xx')}")
# Rack response
[status, headers, body]
rescue Exception => exception
statsd.increment("#{env['REQUEST_PATH']}.response_codes.5xx")
raise
end
def call_with_timing(env)
start = Time.now
result = @app.call(env)
[result, ((Time.now - start) * 1000).round]
end
我想要的是在中间件中找到当前路由,以便我可以发送特定于每个路由的指标。
我尝试了描述here的方法,它告诉env['PATH_INFO']可以提供路径,它确实提供了路径,但它提供了这样的URL参数:/api/products/4但我想要的是/api/products/:id,因为我的目的是跟踪/api/products/:id API 的性能。
env['REQUEST_PATH'] 和 env['REQUEST_URI'] 也给出相同的响应。
Rails.application.routes.router.recognize({"path_info" => env['PATH_INFO']})
或者像这样
Rails.application.routes.router.recognize(env['PATH_INFO'])
但它给出了以下错误:
NoMethodError(未定义方法
path_info' for {"path_info"=>"/api/v1/products/4"}:Hash):find_routes'
vendor/bundle/gems/actionpack-4.2.7.1/lib/action_dispatch/journey/router.rb:100:in
vendor/bundle/gems/actionpack-4.2.7.1/lib/action_dispatch/journey/router.rb:59:inrecognize'call'
vendor/bundle/gems/scout_statsd_rack-0.1.7/lib/scout_statsd_rack.rb:27:in
这个answer 讨论request.original_url,但是我如何访问变量request,我认为它应该与env 相同,但无法从中获得所需的路由。
编辑#1
您可以查看示例 repo here,其中包含 rails 中间件代码 here,可以按照 README 中的说明进行设置,然后可以点击此 API:http://localhost:3000/api/v1/products/1。
编辑#2
我尝试了@MichałMłoźniak 给出的方法,如下所示:
def call(env)
(status, headers, body), response_time = call_with_timing(env)
request = ActionDispatch::Request.new(env)
request = Rack::Request.new("PATH_INFO" => env['REQUEST_PATH'], "REQUEST_METHOD" => env["REQUEST_METHOD"])
Rails.application.routes.router.recognize(request) { |route, params|
puts "I am here"
puts params.inspect
puts route.inspect
}
但我得到以下回复:
I am here
{}
#<ActionDispatch::Journey::Route:0x007fa1833ac628 @name="spree", @app=#<ActionDispatch::Routing::Mapper::Constraints:0x007fa1833ace70 @dispatcher=false, @app=Spree::Core::Engine, @constraints=[]>, @path=#<ActionDispatch::Journey::Path::Pattern:0x007fa1833acc90 @spec=#<ActionDispatch::Journey::Nodes::Slash:0x007fa1833ad230 @left="/", @memo=nil>, @requirements={}, @separators="/.?", @anchored=false, @names=[], @optional_names=[], @required_names=[], @re=/\A\//, @offsets=[0]>, @constraints={:required_defaults=>[]}, @defaults={}, @required_defaults=nil, @required_parts=[], @parts=[], @decorated_ast=nil, @precedence=1, @path_formatter=#<ActionDispatch::Journey::Format:0x007fa1833ac588 @parts=["/"], @children=[], @parameters=[]>>
我也推送了更改here。
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-4 spree