在Ruby / Rails中,如何在URL中编码/转义特殊字符?

在使用OpenURI open(url)之前,如何编码或“转义”URL?

我们使用OpenURI打开远程URL并返回xml:

 getresult = open(url).read 

问题是URL包含一些用户输入文本,其中包含空格和其他字符,包括“+”,“&”,“?”等可能,因此我们需要安全地转义URL。 我在使用Net :: HTTP时看到了很多例子,但是没有为OpenURI找到任何例子。

我们还需要能够解析我们在会话变量中收到的类似字符串,因此我们需要倒数函数。

Ruby有内置的URI库和Addressable gem,特别是Addressable :: URI

我更喜欢Addressable :: URI。 它是function齐全的,当您使用query_values=方法时,它会为您处理编码。

我已经看到一些关于URI经历了一些成长的痛苦的讨论,所以我倾向于将它单独用于处理编码/转义,直到这些事情得到解决:

不要使用URI.escape因为它已在1.9中弃用。

Rails的Active Support添加了Hash#to_query

  {foo: 'asd asdf', bar: '"<#$dfs'}.to_query # => "bar=%22%3C%23%24dfs&foo=asd+asdf" 

此外,正如您所看到的那样,它尝试以相同的方式对查询参数进行排序,这对HTTP缓存很有用。

Ruby标准库拯救:

 require 'uri' user_text = URI.escape(user_text) url = "http://example.com/#{user_text}" result = open(url).read 

有关URI :: Escape模块的文档,请参阅更多内容。 它还有一个方法来做反向( unescape

您必须考虑的主要事项是编写完整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"}]