Rails - redirect to current url without one of the GET params

ε祈祈猫儿з 提交于 2021-02-18 08:54:12

问题


I have a very simple problem in a Rails app that I can't find an elegant solution to.

I have a URL like: http://www.example.com/some-path/?foo=123&baz=456

And I want to process one of the params and do a redirect to: http://www.example.com/some-path/?baz=456

I want this to work generally for any URL with param "foo", so I don't want to specify "baz" in the rewrite code.

What I want is something like:

redirect_to request.path, :params => request.query_parameters.except(:foo)

Except that doesn't quite work. I know I can regex or parse the query string manually but I assume there's a better way.


回答1:


The best way which I have found so far is to use:

url_for(params.except(:obsolete_param_name))

UPDATE

As grosser mentioned this opens up a security hole in your application as an attacker can pass a host as a url param and redirect the user to a different website. In order to prevent this you can use rap1ds's suggestion and specify that only the path has to be used.

You can use a helper function like this one for this purpose:

def secure_path_for(params, *excluded_params)
  url_for(params.except(*excluded_params).merge(only_path: true))
end



回答2:


What about just deleting params[:foo] before you pass it along. Maybe something like:

params.delete[:foo]
redirect_to request.path, :params => params

It's not really elegant, but it only adds one line. Params by the way is a helper method that get's the url's current parameters




回答3:


In rails 5 you will get non-sanitized request parameters error if you attempt to do this url_for(params.except(:param))

So I found this way to do this:

request_url = request.url # eg. http://qwe.com/path?param1=1&param2=2

query_hash = Rack::Utils.parse_query(URI.parse(request_url).query).except('param1')
url = query_hash.empty? ? request.path : "#{request.path}?#{query_hash.to_query}"

puts url #=> /path?my_param2=2

redirect_to url



回答4:


uri = URI.parse(request.url)
new_query = uri.query.split("&").reject{|pair|
  k,v = pair.split("=")
  k =~ /^foo\[?/ # reject params named "foo" or "foo[anything"
}.join("&")
# if the new querystring is empty, assign nil instead of "" so we don't
# end up with a solitary question mark at the end of the url.
uri.query = (new_query.empty? ? nil : new_query)
redirect_to uri.to_s

I came to the above solution after running into some non-obvious problems with trying to do things the "Rails way," if there is such a way, to solve this issue. For instance:

  • Rails parameter parsing will automagically instantiate arrays and hashes for query params that use the special square bracket syntax: ?x[a]=1&y[]=2 becomes {"x"=>{"a"=>"1"}, "y"=>["2"]} and so on, so code that uses the provided querystring and param routines are tricky to deal with in this regard. And filtering params by raw string value can be difficult as a result. Even the non-rails/rack CGI module will give you arrays instead of strings for the param values.
  • The rails params hash includes both GET, POST, and routing parameters, such as :action and :controller so you couldn't just re-use that to reconstruct a querystring anyway.
  • As such, the URL helpers like url_for are not much help.

Given these issues I found I was not able to use provided framework functionality to get a pure and unmolested querystring, reproduced as-is from the current request, that simply and only removes one parameter. The code above seems to work well, however.



来源:https://stackoverflow.com/questions/13461178/rails-redirect-to-current-url-without-one-of-the-get-params

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!