通过 recognize_path 将请求 URL 参数与 rails 路由匹配

Match request URL params with rails routes via recognize_path

我想通过 recognize_path 检查 routes.rb 中是否确实存在任何传入请求作为条目,就像这样

def path_exists?(path)
  Rails.application.routes.recognize_path(path)
  true
  rescue
   false
end

这适用于大多数 URL,但如果 URL 有参数,则无法识别它。

示例:

在 routes.rb 中,假设我有这样的条目

put "foo/bar/:param" => "foo#bar"

并且传入请求 URL 的格式为 /foo/bar/5

然后函数recognize_path无法识别URL因为参数的值是5但它匹配:param

如何使用 recognize_path 或任何其他类似函数将具有参数的请求与其在 routes.rb 中的条目匹配?

原因

我正在过滤掉使用随机 URL 攻击服务器的恶意尝试,例如 /dump.sql.tar.gz/conf.xz,等等,使用 gem rack::attack and throttling 请求,其 URL 不是 routes.rb 的一部分。于是就有了上面的问题。

您可以使用以下代码片段完成此操作:

Rails.application.routes.routes.to_a.reduce(false) do |exists, route|
 route.path.to_regexp.match?(path) || exists
end

但我确实认为最好的选择是使用自定义逻辑处理 404 错误。为什么要做路由器已经为您做的事情?这是一个例子:

config.exceptions_app = self.routes
# This will route any exceptions caught to your router Rack app. Now you'll want to define routes to display those errors yourself:

# config/routes.rb
get "/404", :to => "errors#not_found"
get "/422", :to => "errors#unacceptable"
get "/500", :to => "errors#internal_error"

(摘自http://web.archive.org/web/20141231234828/http://wearestac.com/blog/dynamic-error-pages-in-rails

然后你可以在ErrorsController

上做任何你想做的逻辑
def path_exists?(req_current)
 path_exists_val = false
 Rails.application.routes.router.recognize(req_current) do |route, params|
  if route.required_defaults[:controller] and route.required_defaults[:action]
   path_exists_val = true
  end
 end
 path_exists_val
end

这是我最终使用 ActionDispatch::Journey::Route 对象将所有可能的 URL 与其各自的控制器和操作相匹配的代码,我从@cesartalves 对问题的回答中了解到,因此标记为作为答案。

欢迎提出任何改进代码的建议!

PS。我是 Rails 上 Ruby 的新手。