Главное, что вам нужно учесть, это то, что вы должны экранировать ключи и значения отдельно до того, как вы составите полный URL.
Все методы, которые получают полный URL-адрес и впоследствии пытаются его избежать, не работают, поскольку они не могут определить, должен ли какой-либо символ &
или =
быть разделителем или, возможно, частью значения (или часть ключа).
Библиотека CGI, кажется, работает хорошо, за исключением символа пробела, который традиционно кодировался как +
, и в настоящее время должен кодироваться как %20
. Но это легко исправить.
Пожалуйста, примите во внимание следующее:
require 'cgi'
def encode_component(s)
# The space-encoding is a problem:
CGI.escape(s).gsub('+','%20')
end
def url_with_params(path, args = {})
return path if args.empty?
path + "?" + args.map do |k,v|
"#{encode_component(k.to_s)}=#{encode_component(v.to_s)}"
end.join("&")
end
def params_from_url(url)
path,query = url.split('?',2)
return [path,{}] unless query
q = query.split('&').inject({}) do |memo,p|
k,v = p.split('=',2)
memo[CGI.unescape(k)] = CGI.unescape(v)
memo
end
return [path, q]
end
u = url_with_params( "http://example.com",
"x[1]" => "& ?=/",
"2+2=4" => "true" )
# "http://example.com?x%5B1%5D=%26%20%3F%3D%2F&2%2B2%3D4=true"
params_from_url(u)
# ["http://example.com", {"x[1]"=>"& ?=/", "2+2=4"=>"true"}]