考慮しなければならない主なことは、完全な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"}]