通过 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 的新手。
我想通过 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 的新手。