URI.escape和CGI.escape有什么区别?

URI.escape和CGI.escape有什么区别?

问题描述:

URI.escapeCGI.escape有什么区别,我应该使用哪一个?URI.escape和CGI.escape有什么区别?

有一些小的差异,但重要的一点是,URI.escape一直在红宝石1.9.2 deprecated ...所以使用CGI::escapeERB::Util.url_encode

有一个长期的讨论on ruby-core有兴趣的人还提到WEBrick::HTTPUtils.escapeWEBrick::HTTPUtils.escape_form

+7

只是为了增加迷惑 - 我只是看到了http://stackoverflow.com/questions/4967608/in-ruby-rails-how-can-i-encode-escape-special-characters-in-urls 哪里评论有人提到,CGI逃生使用“+”,而不是20%的空间,而这违反了“规范” ... – 2012-07-19 11:24:25

+11

另一种方法是使用'ERB :: Util.url_encode',妥善使用'%20'的空间 – riffraff 2012-10-16 08:40:39

+0

AFAIK,URI.escape在1.9.2和1.9.3中不推荐使用。我错过了什么? – Ernest 2012-10-23 16:56:18

URI.escape采用第二个参数,可以让您标记什么是不安全的。见APIDock:

http://apidock.com/ruby/CGI/escape/class

http://apidock.com/ruby/URI/Escape/escape

+0

大答案@Robert斯派克。 – lightyrs 2013-03-30 08:03:19

CGI::escape适用于转义文本段,以便它们可以用于url查询参数('?'之后的字符串)。例如,如果你想在url中包含斜线字符参数,你首先将CGI :: escape字符串转义出来,然后将其插入到url中。

但是在Rails中你可能不会直接使用它。通常你使用hash.to_param,这将使用CGI::escape


URI::escape有利于逃避这是不正确转义的URL。例如,一些网站在其标记标签中输出错误/未转义的网址。如果您的程序使用这些网址获取更多资源,OpenURI会抱怨这些网址无效。您需要URI::escape这些才能使其成为有效的网址。所以它被用来转义整个URI字符串以使其正确。用我的话来说,URI :: unescape使人类可读的URL,URI :: escape使它对浏览器有效。

这些是我的外行人的任期,并随时纠正这些问题。

斧头和剑之间有什么区别,我应该使用哪一个?那么它取决于你需要做什么。

URI.escape应该将字符串(URL)编码为所谓的“Percent-encoding”。

CGI::escape来自CGI规范,它描述了如何在Web服务器和应用程序之间编码/解码数据。

现在,假设您需要在您的应用中转义URI。这是一个更具体的用例。 为此,Ruby社区多年来一直使用URI.escapeURI.escape的问题在于它无法处理RFC-3896规范。

URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog' 
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog" 

URI.escape被标记为过时:

而且当前URI.encode是简单GSUB。但我认为应该将 拆分成一个URI组件,然后将每个组件都转义出来,最后 加入它们。

所以当前的URI。编码被认为是有害的并被弃用。这会使 被删除或急剧改变行为。

什么是更换在这个时候?

正如我上面所说的,当前的URI.encode在规范级别是错误的。所以我们 将不会提供确切的替换。更换将根据其 用例而有所不同。

https://bugs.ruby-lang.org/issues/4167

不幸的是,没有一个关于它的单个字的文档,了解它是检查源,或运行在详细级别(-wW2)警告脚本的唯一途径(或使用一些谷歌福)。

一些proposed使用CGI::Escape查询参数,因为你无法逃脱整个URI:

CGI::escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog' 
# => "http%3A%2F%2Fgoogle.com%2Ffoo%3Fbar%3Dat%23anchor%26title%3DMy+Blog+%26+Your+Blog" 

CGI::escape应该仅用于查询参数,但结果将是,再次,对规范。实际上最常见的用例中逸出形式的数据,诸如在发送一个application/x-www-form-urlencoded POST请求。

还提到WEBrick::HTTPUtils.escape没有太大的改善(再次,它只是一个简单的gsub,这是,海事组织,甚至比URI.escape一个糟糕的选择):

WEBrick::HTTPUtils.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog' 
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog" 

的最接近规范似乎是Addressable宝石:

require 'addressable/uri' 
Addressable::URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog' 
# => "http://google.com/foo?bar=at#anchor&title=My%20Blog%20&%20Your%20Blog" 

注意,不像以前所有的选项,可寻址没有逃脱#,这是预期的行为。要保持#散列URI路径,但不是在URI查询。

唯一剩下的问题是,我们没有正确地逃过我们的查询参数,这使我们得出结论:我们不应该对整个URI一个方法,因为没有完美的解决方案(到目前为止)。 正如你看到的&不是从“我的博客&你的Blog”逃过一劫。我们需要为查询参数使用不同形式的转义,用户可以在URL中放置具有特殊含义的不同字符。输入网址编码。 URL编码应该用于每一个 “可疑” 的查询值,类似于ERB::Util.url_encode做:

ERB::Util.url_encode "My Blod & Your Blog" 
# => "My%20Blod%20%26%20Your%20Blog"" 

这很酷,但我们已经要求寻址:

uri = Addressable::URI.parse("http://www.go.com/foo") 
# => #<Addressable::URI:0x186feb0 URI:http://www.go.com/foo> 
uri.query_values = {title: "My Blog & Your Blog"} 
uri.normalize.to_s 
# => "http://www.go.com/foo?title=My%20Blog%20%26%20Your%20Blog" 

结论:

  • 不要使用URI.escape或类似
  • 使用CGI::escape如果你只需要形式逃逸
  • 如果需要使用URI来工作,使用可寻址,它提供了URL编码,编码形式和规范化的URL。
  • 如果它是一个Rails项目,退房 “How do I URL-escape a string in Rails?
+0

非常感谢您的信息。它确实摆脱了一些锄头测试警告。下面有一把耙子和一把锄头。 – 2014-09-24 07:18:20

+0

很好的解释@Ernest,但问题在于它不适用于我不想创建(并且无法控制)的外部URL。例如抓取工具从网页中读取URL,然后尝试访问这些URL(在访问之前需要对其进行编码)。 – 2014-11-09 23:23:40

+0

@amit_saxena如果你能提供具有'Addressable'为你的宝石之一,你可以先解析URL,f.i. http://www.rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse – Ernest 2014-11-10 15:50:58

不同的是,URI.escape是不工作...

CGI.escape"/en/test?asd=qwe" 
=> "%2Fen%2Ftest%3Fasd%3Dqwe" 

URI.escape"/en/test?asd=qwe" 
=> "/en/test?asd=qwe"