I want to check if any incoming request actually exists in routes.rb as an entry via recognize_path
like this
def path_exists?(path)
Rails.application.routes.recognize_path(path)
true
rescue
false
end
This works for most URLs but if the URL has a parameter, then it fails to recognize it.
Example:
In routes.rb, say I have an entry like this
put "foo/bar/:param" => "foo#bar"
and the incoming request URL is of the form /foo/bar/5
Then the function recognize_path
doesn't recognize the URL as the value of the parameter is 5
but it is matched with :param
How do I match requests that have parameters to their entries in routes.rb using recognize_path
or any other similar function?
Reason
I'm filtering out malicious attempts to hit the server using random URLs like /dump.sql.tar.gz, /conf.xz, etc using the gem rack::attack and throttling requests whose URLs are not a part of routes.rb. Hence the above problem.
CodePudding user response:
You can accomplish that with the following snippet:
Rails.application.routes.routes.to_a.reduce(false) do |exists, route|
route.path.to_regexp.match?(path) || exists
end
But I do think the best choice is handling 404 errors using custom logic. Why doing what the router already does for you? Here's an example:
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"
(Extracted from http://web.archive.org/web/20141231234828/http://wearestac.com/blog/dynamic-error-pages-in-rails)
Then you can do whatever logic you want to do on ErrorsController
CodePudding user response:
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
This is the code that I ended up going with to match all the possible URLs with their respective controller and action using the ActionDispatch::Journey::Route
object which I learned about from @cesartalves answer to the question and hence marked that as the answer.
Any suggestions to improve the code are welcome!
PS. I'm new to Ruby on Rails.