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

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

105721 次浏览

Escape 采用第二个参数来标记不安全的参数。参见 APIDock:

Http://apidock.com/ruby/cgi/escape/class

Http://apidock.com/ruby/uri/escape/escape

虽然有一些细微的差别,但重要的是 URI.escape在 Ruby1.9.2中一直是 不赞成... 所以使用 CGI::escapeERB: : Util.url _ encode

有一个很长的讨论 红宝石核心为那些感兴趣,也提到了 HTTPUtils.escapeWEBrick: : HTTPUtils.escape _ form

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

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


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

这些是我的门外汉术语,请随意更正。

斧头和剑有什么区别? 我该用哪一把?那么它 看情况对你需要做什么。

URI.escape应该将一个字符串(URL)编码为所谓的“ 百分号编码”。

CGI::escape来自于 电脑合成规范,该规范描述了在 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)(或者使用一些 google-fu)。

一些 提议使用 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"

最接近规格的似乎是 可寻址宝石:

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 项目,检查“ 如何在 Rails 中对字符串进行 URL 转义?

区别在于 URI.escape 无法工作..。

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


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

Escape 用于转义查询字符串中的 URL 值。所有不属于 ALPHA、 DIGIT、“ _”、“-”、“”的字符字符集转义。

但这会导致 URL 不正确,因为 URL 需要包含“/”、“ :”、“ ?”,’[’,’&’,’=’,’;’。也许还有更多我一时想不起来的事。

Escape 不使用这些 URL 字符,而是尝试查找要转义的查询字符串键和值。然而,这确实不能依赖,因为值可以有各种各样的字符来阻止容易的转义。基本上,已经太晚了。但是如果 URL 可以依赖于简单(值中没有’&’和’=’等) ,那么这个函数可以用来转义可能不可读或非法的字符。

一般情况下——在将单个键和值与“ &”连接起来并在“ ?”后面添加它们之前,始终对它们使用 CGI 转义符.

CGI.escape 不能与 OpenProjectAPI 一起工作。它编码的是[] ,: 而不是 + 。我把它们拼凑在一起,目前看来对 OpenProject 的 API 很有用。但我肯定少了一些。Gsub 的。它可能几乎和 URI.escape 一样糟糕,但是它不会提供过时的错误。

class XXX
def self.encode(path)
path, query = path.split("?", 2)
return path if query.nil?
query = CGI.escape(query).gsub("%3A", ":").gsub("%3D","=").gsub("%5B","[").gsub("%5D","]").gsub("%2C",",").gsub("+","%20")
return [path,query].join("?")
end
end


XXX.encode("http://test.com/some/path?query=[box: \"cart\"]")
URI.encode("http://test.com/some/path?query=[box: \"cart\"]")

两种产出都是:

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