问题 为什么URI.escape不能单引号?


为什么不呢 URI.escape 逃避单引号?

URI.escape("foo'bar\" baz")
=> "foo'bar%22%20baz"

7778
2017-10-11 20:12


起源

因为单引号是合法的URI字符。 stackoverflow.com/questions/1547899/... - Dave Newton
嗯..虽然它们是保留的,意味着它们被允许但具有特殊的句法意义。在这种情况下,我不希望它们具有特殊含义,它是用户输入的数据,不应将其解释为语法,而应由浏览器和Web应用程序以及其间的所有层解释为数据。所以我想真正的问题是,“逃避”是什么意思...... - John Bachir
根据 文档 它会逃脱“不安全”的角色 REGEX::UNSAFE。你可以传递自己的。 - Dave Newton
FWIW我在这里是因为AWS Cloudfront希望将URI中的单引号转义为 %27,当您尝试运行失效时。所以,这对某些人来说是合法的,而对于其他人而言我认为并不合法。 - Max Williams


答案:


出于同样的原因,它不会逃脱 ? 要么 / 要么 :等等。 URI.escape() 仅转义不能在URL中使用的字符 一点都不,而不是具有特殊含义的字符。

你在寻找什么 CGI.escape()

require "cgi"
CGI.escape("foo'bar\" baz")
=> "foo%27bar%22+baz"

9
2017-10-11 21:45



我不确定这有多大帮助。 CGI转义与URI转义没有做同样的事情,并且它们不可互换。 - cbmanica
@cbmanica。这是事实,但是大多数使用此库的人实际上都希望对字符串进行URL编码。看到 这个优秀的答案 在替代方案上有一个很好的纲要。 - Mark Thomas


这是一个老问题,但答案在很长一段时间内都没有更新。我以为我会为遇到同样问题的其他人更新这个。我发现的解决方案是 发布在这里: 使用 ERB::Util.url_encode 如果你有 erb 模块可用。这照顾了单引号& * 对我来说也是如此。

CGI::escape 没有正确地逃避空间(%20)与加号相对。


4
2017-07-12 00:54





根据文件, URI.escape(str [, unsafe]) 使用匹配必须用代码替换的所有符号的正则表达式。默认情况下,该方法使用REGEXP :: UNSAFE。当此参数是String时,它表示字符集。

在你的情况下,要修改 URI.escape 为了逃避单引号你可以做这样的事......

reserved_characters = /[^a-zA-Z0-9\-\.\_\~]/
URI.escape(YOUR_STRING, reserved_characters)

说明:有关规范的一些信息......

使用[rfc3986]转义所有参数名称和值   百分比编码(%xx)机制。字符不在无保留   必须对字符集([rfc3986]第2.3节)进行编码。中的人物   不得对未保留的字符集进行编码。十六进制   编码中的字符必须为大写。文本名称和值必须   在[rfc3629]按百分比编码之前编码为utf-8个八位字节。


1
2018-03-09 19:36



不推荐使用URI.escape。尽管它仍然存在,但最好使用此处发布的其他解决方案之一。 - Mark Thomas
@MarkThomas我同意。我把它放在这里用于存档目的,以详细说明如何修改正如在传递中提到的正则表达式。 - King'ori Maina


我知道这已经得到了回答,但我想要的是略有不同的东西,我想我也可以发布它:我想在网址中保留“/”,但是要逃避所有其他非标准字符。我这样做了:

#public filename is a *nix filepath, 
#like `"/images/isn't/this a /horrible filepath/hello.png"`

public_filename.split("/").collect{|s| ERB::Util.url_encode(s)}.join("/")
=> "/images/isn%27t/this%20a%20/horrible%20filepath/hello.png"

当我为AWS Cloudfront编写缓存失效时,我需要逃避单引号,它不喜欢单引号并期望它们被转义。上面应该创建一个比标准URI.escape更安全的uri但仍然看起来像一个URI(CGI Escape通过转义“/”来打破uri格式)。


0
2018-03-28 09:48