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

时间:2011-02-11 09:52:43

标签: ruby urlencode open-uri

在将OpenURI用于open(url)之前,如何对URL进行编码或“转义”?

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

getresult = open(url).read

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

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

4 个答案:

答案 0 :(得分:28)

不要使用{1.9}中已弃用的URI.escape

Rails的有效支持添加了Hash#to_query

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

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

答案 1 :(得分:14)

红宝石标准库拯救:

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

点击docs for the URI::Escape module了解详情。它还有一个方法来执行逆(unescape

答案 2 :(得分:8)

您必须考虑的主要事项是您必须单独转义键和值才能构成完整的网址

获取完整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"}]

答案 3 :(得分:2)

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

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

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