Home > OS >  Match request URL params with rails routes via recognize_path
Match request URL params with rails routes via recognize_path

Time:09-17

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.

  • Related