Stefan
Stefan

Reputation: 9329

Rails truncating of parameters with '.' in urls

I am trying to send an IP address as a parameter to a Rails method destroy in a url. There is a problem if the parameter includes .; I get not found errors, this is the log generated:

Started DELETE "/admin/user/stefan-admin/whitelist/4.3.2.1" for 127.0.0.1 at 2013-07-17 09:31:18 +0100
Processing by ErrorsController#error_404 as 
  Parameters: {"not_found"=>"admin/user/stefan-admin/whitelist/4.3.2"}
WARNING: Can't verify CSRF token authenticity
Session: {:user=>"admin", :role=>:admin, :user_id=>"stefan-admin"}
Completed 404 Not Found in 30ms (Views: 1.1ms | ActiveRecord: 0.0ms)

The not found message has a truncated ip address. If I use a parameter without ., e.g. abc, I don't get the not found error, and the destroy method is called.

Rails received the url, but then mangled it internally, possibly because it is processing . as an extension. Is there some way to turn off this behaviour or escape the url to avoid it?

Upvotes: 6

Views: 1353

Answers (4)

Martin M
Martin M

Reputation: 8638

The reason for the "truncated" ip address is the (optional) (.:format) that resources, 'get', 'match' etc. generate on every route.

You can specify a dedicate route without the format like:

match '/admin/user/:id/whitelist/*ip', to: 'controller#action', format: false

pay attention to the * at the last parameter. It collects the whole rest of the url.

Upvotes: 4

Billy Chan
Billy Chan

Reputation: 24815

At first glance the problem could be resolved by manipulating the parameters or routing. By thinking a bit more, you will notice two more problems in your scheme:

  1. You used GET request to process a delete action
  2. The dots in url, if not for name extension, is very ugly.

So, instead of solving the problem directly, I suggest you to:

Review the view code containing the request link. It's better to be a button_to, or a link_to with delete method and UJS support.

By this you'll send a POST request to server without ip in URL. And you don't need any change in controller code.

Upvotes: 1

yannick
yannick

Reputation: 661

You need to add a constraint to the routes to allow dots in params

resources :whitelists, :constraints => { :id => /[0-9.]+/ }

Or something of that kind in your routes.rb, it depends on how you write your routes but the constraints part stay the same

Upvotes: 5

Slicedpan
Slicedpan

Reputation: 5015

Found a hacky way to do it. If your route looks like this

match 'controller/:some_param' => 'controller#action'

Then in the controller action, you can do something like this

actual_param = params[:some_param]
if params[:format]
  actual_param << "." << params[:format]
end

Then use actual_param to identify the correct resource

Upvotes: 0

Related Questions