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

时间:2010-05-13 02:32:53

标签: ruby

URI.escapeCGI.escape之间有什么区别?我应该使用哪一个?

7 个答案:

答案 0 :(得分:205)

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

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.encode被认为是有害的并且已被弃用。这将   被删除或大幅改变行为。

     
    

目前有什么替代品?

  
     

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

     

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

不幸的是,在文档中没有关于它的单词,了解它的唯一方法是检查源代码,或者使用详细级别的警告(-wW2)运行脚本(或使用一些谷歌) -fu)。

有些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,即IMO,甚至比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"

请注意,与以前的所有选项不同,Addressable不会转义#,这是预期的行为。您希望将#哈希保留在URI路径中,但不保留在URI查询中。

唯一的问题是我们没有正确地转义我们的查询参数,这使我们得出结论:我们不应该对整个URI使用单一方法,因为没有完美的解决方案(到目前为止)。 如您所见&未从“我的博客和您的博客”中转义。我们需要对查询参数使用不同形式的转义,其中用户可以在URL中放置具有特殊含义的不同字符。输入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,请使用Addressable,它提供URL编码,表单编码和规范化URL。
  • 如果是Rails项目,请查看“How do I URL-escape a string in Rails?

答案 1 :(得分:115)

存在一些小的差异,但重要的是,{1.9}中的URI.escapedeprecated ...所以请使用CGI::escapeERB::Util.url_encode。< / p>

对于那些感兴趣的人,on ruby-coreWEBrick::HTTPUtils.escape进行了长时间的讨论WEBrick::HTTPUtils.escape_form

答案 2 :(得分:9)

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

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

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

答案 3 :(得分:6)

CGI::escape适用于转义文本段,因此可以在url查询参数('?'后面的字符串)中使用它们。例如,如果您希望在url中包含包含斜杠字符的参数,则CGI ::首先转义该字符串,然后将其插入url中。

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


URI::escape适用于转义未正确转义的网址。例如,某些网站在其锚标记中输出错误/未转义的网址。如果您的程序使用这些网址获取更多资源,OpenURI会抱怨网址无效。您需要URI::escape这些才能使其成为有效的网址。因此它用于转义整个URI字符串以使其正确。在我的单词URI :: unescape中,人类可以读取url,而URI :: escape使它对浏览器有效。

这些是我的外行任期,随时可以纠正这些。

答案 4 :(得分:2)

区别在于URI.escape不起作用......

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

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

答案 5 :(得分:0)

CGI.escape用于转义查询字符串中的URL值。不属于ALPHA,DIGIT,'_','-','。'的所有字符和''字符集被转义。

但这将使URL不正确,因为url需要具有'/',':','?','[','&','='和';'。也许我想不到的更多。

URI.escape仅保留这些URL字符,然后尝试查找要转义的查询字符串键和值。但是,实际上不能依赖于此,因为值可以包含各种字符,从而容易逃脱。基本上,为时已晚。但是,如果可以将URL简化为简单的值(值中没有'&'和'='等),则可以使用此函数来转义可能不可读或非法的字符。

通常-在将各个键和值与'&'联接并在'?'之后添加它们之前,请始终对各个键和值使用CGI.escape。

答案 6 :(得分:0)

CGI.escape不适用于OpenProject API。它对[] ,:而不是+进行编码。我一起破解了这一点,到目前为止看来,它对于OpenProject的API仍然有效。但我确定它缺少一些.gsub。它可能几乎与URI.escape一样糟糕,但不会给您带来过时的错误。

<list>
<message ref="00001">
    <entry>
        <orderid>P001</orderid>
        <timestamp>20200109085816092</timestamp>
    </entry>
</message>
<message ref="00002">
    <entry>
        <orderid>P002</orderid>
        <timestamp>20200109085813556</timestamp>
    </entry>
</message>
<message ref="00003">
    <entry>
        <orderid>P003</orderid>
        <timestamp>20200109085814612</timestamp>
    </entry>
</message>
<message ref="00004"/>
<message ref="00005"/>
<message ref="00006"/>

两个输出:

=>“ http://test.com/some/path?query=[box:%20%22cart%22]
=>“ http://test.com/some/path?query=[box:%20%22cart%22]