Rails - перенаправление на текущий URL-адрес без одного из параметров GET
У меня очень простая проблема в приложении Rails, что я не могу найти элегантное решение.
У меня есть URL-адрес:
http://www.example.com/some-path/?foo=123&baz=456
И я хочу обработать один из параметров и сделать перенаправление:
http://www.example.com/some-path/?baz=456
Я хочу, чтобы это работало вообще для любого URL с параметром "foo", поэтому я не хочу указывать "baz" в коде перезаписи.
Я хочу что-то вроде:
redirect_to request.path, :params => request.query_parameters.except(:foo)
За исключением того, что это не совсем работает. Я знаю, что я могу регулярное выражение или разбор строки запроса вручную, но я предполагаю, что лучший способ.
Ответы
Ответ 1
Лучшим способом, который я нашел до сих пор, является использование:
url_for(params.except(:obsolete_param_name))
UPDATE
Как упоминалось в grosser, это откроет дыру в вашем приложении, поскольку злоумышленник может передать хост в качестве параметра url и перенаправить пользователя на другой веб-сайт, Чтобы предотвратить это, вы можете использовать rap1ds предложение и указать, что нужно использовать только путь.
Для этой цели вы можете использовать вспомогательную функцию:
def secure_path_for(params, *excluded_params)
url_for(params.except(*excluded_params).merge(only_path: true))
end
Ответ 2
Как просто удалить параметры [: foo], прежде чем передавать его. Может быть, что-то вроде:
params.delete[:foo]
redirect_to request.path, :params => params
Это не очень элегантно, но добавляет только одну строку. Парамс, между прочим, является вспомогательным методом, который получает параметры тока url
Ответ 3
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
Я пришел к вышеупомянутому решению после того, как столкнулся с некоторыми неочевидными проблемами, пытаясь сделать что-то "Rails way", если есть такой способ, чтобы решить эту проблему. Например:
- Разбор параметров Rails автоматически создает экземпляры массивов и хэшей для параметров запроса, которые используют специальный синтаксис квадратной скобки:
?x[a]=1&y[]=2
становится {"x"=>{"a"=>"1"}, "y"=>["2"]}
и т.д., поэтому код, который использует предоставленные процедуры запроса и парамагменты, с трудом справляется это. И фильтрация параметров с помощью необработанного значения строки может быть затруднена. Даже модуль CGI без рельсов/стойки даст вам массивы вместо строк для значений параметров.
- Рельсы
params
содержат как GET, POST, так и параметры маршрутизации, такие как :action
и :controller
, поэтому вы не можете просто повторно использовать это, чтобы в любом случае восстановить цепочку.
- Таким образом, помощники URL, такие как url_for, не очень помогают.
Учитывая эти проблемы, я обнаружил, что не смог использовать предоставленные функциональные возможности фреймворка, чтобы получить чистую и невозвращенную последовательность запросов, воспроизведенную как есть из текущего запроса, которая просто и только удаляет один параметр. Однако код выше работает хорошо.
Ответ 4
В рельсах 5 вы получите несанитарные параметры запроса, если вы попытаетесь сделать это url_for(params.except(:param))
Итак, я нашел способ сделать это:
request_url = request.url # eg. http://qwe.com/path?param1=1¶m2=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