18

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

我们使用 OpenURI 打开一个远程 url 并返回 xml:

getresult = open(url).read

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

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

4

4 回答 4

32

不要使用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 缓存很有用。

于 2012-11-29T13:06:14.560 回答
14

Ruby 标准库的救援:

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

在 URI::Escape 模块的文档中查看更多信息。它也有一个方法来做逆 ( unescape)

于 2011-02-11T10:17:57.287 回答
8

您必须考虑的主要事情是,在编写完整的 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"}]
于 2011-12-08T16:28:27.737 回答
2

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

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

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

于 2011-02-11T13:35:04.720 回答