URL 中的空格何时编码为 +
,何时编码为 %20
?
来自 Wikipedia(添加了重点和链接):
当提交已输入 HTML 表单的数据时,表单字段名称和值将被编码并使用方法 GET 或 POST 或过去通过电子邮件在 HTTP 请求消息中发送到服务器。默认使用的编码基于通用 URI 百分比编码规则的早期版本,并进行了许多修改,例如换行规范化和用“+”而不是“%20”替换空格。以这种方式编码的数据的 MIME 类型是 application/x-www-form-urlencoded,目前在 HTML 和 XForms 规范中定义(仍然以非常过时的方式)。
因此,real 百分比编码使用 %20
,而 URL 中的表单数据是使用 +
的修改形式。因此,您很可能只会在 ?
之后的查询字符串中的 URL 中看到 +
。
这种混淆是因为 URL 直到今天仍然“损坏”。
从 a blog post:
以“http://www.google.com”为例。这是一个网址。 URL 是统一资源定位器,实际上是指向网页的指针(在大多数情况下)。自 1994 年第一个规范以来,URL 实际上具有非常明确的结构。我们可以提取有关“http://www.google.com” URL 的详细信息:+------------- --+--------------------------------+ |零件 |数据 | +---------------+-------------------+ |方案 | http | |主持人 | www.google.com | +---------------+-------------------+ 如果我们查看更复杂的 URL,例如:“https ://bob:bobby@www.lunatech.com:8080/file;p=1?q=2#third" 我们可以提取以下信息:+--------------- --+------------+ |零件 |数据 | +-----------------+---------------------+ |方案 | https | |用户 |鲍勃 | |密码 |鲍比 | |主持人 | www.lunatech.com | |港口 | 8080 | |路径 | /文件;p=1 | |路径参数 | p=1 | |查询 | q=2 | |片段 |第三| +-----------------+---------------------+ https://bob:bobby @www.lunatech.com:8080/file;p=1?q=2#third \___/ \_/ \___/ \______________/ \__/\_______/ \_/ \___/ | | | | | | \_/ | |方案用户密码主机端口路径| |片段\_____________________________/ |查询 |路径参数 权限 每个部分的保留字符不同。对于 HTTP URL,路径片段部分中的空格必须编码为“%20”(不是,绝对不是“+”),而路径片段部分中的“+”字符可以不编码。现在在查询部分,空格可以编码为“+”(为了向后兼容:不要尝试在 URI 标准中搜索它)或“%20”,而“+”字符(由于这种歧义) 必须转义为“%2B”。这意味着“蓝色+浅蓝色”字符串必须在路径和查询部分中进行不同的编码:“http://example.com/blue+light%20blue?blue%2Blight+blue”。从那里你可以推断,如果没有对 URL 结构的句法意识,编码一个完全构造的 URL 是不可能的。
这归结为:
您应该在 ?
之前和 +
之后有 %20
。
key1=value1&key1=value2
,其中键和值按照 encodeURIComponent
遵循的任何规则进行编码,但 AFAIK 查询部分的内容完全 100% 取决于应用程序。其他然后它只进入第一个 #
没有官方编码。
?
之前使用 %20 而不是 +,但在?
这只是口味问题。看在上帝的份上,人们,总是使用基于百分号的编码,并为更重要的东西腾出一些大脑空间。
我会推荐%20
。
你对它们进行硬编码吗?
但是,这在各种语言中并不是很一致。如果我没记错的话,在 PHP 中 urlencode()
将空格视为 +
而 Python 的 urlencode()
将它们视为 %20
。
编辑:
看来我弄错了。 Python 的 urlencode()
(至少在 2.7.2 中)使用 quote_plus()
而不是 quote()
,因此将空格编码为“+”。 W3C 的建议似乎也是这里的“+”:http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
事实上,您可以关注 Python 自己的问题跟踪器上关于使用什么来编码空格的有趣辩论:http://bugs.python.org/issue13866。
编辑#2:
我知道编码“”最常见的方式是“+”,但只是一个注释,可能只是我,但我觉得这有点令人困惑:
import urllib
print(urllib.urlencode({' ' : '+ '})
>>> '+=%2B+'
URLEncoder.encode()
方法也将其转换为 +
。
在 URL 的“application/x-www-form-urlencoded”内容类型键值对查询部分中,空格只能编码为“+”。在我看来,这是可以的,而不是必须的。在其余的 URL 中,它被编码为 %20。
在我看来,最好始终将空格编码为 %20,而不是“+”,即使在 URL 的查询部分也是如此,因为 HTML 规范 (RFC 1866) 指定空格字符应编码为“ +”在“application/x-www-form-urlencoded”内容类型键值对中(参见第 8.2.1 段。第 1 小段。)
这种编码表单数据的方式也在后面的 HTML 规范中给出。例如,在 HTML 4.01 Specification 中查找有关 application/x-www-form-urlencoded 的相关段落,等等。
这是 URL 中的示例字符串,其中 HTML 规范允许将空格编码为加号:“http://example.com/over/there?name=foo+bar”。所以,只有在“?”之后,空格才能被加号代替。在其他情况下,空格应编码为 %20。但由于很难正确确定上下文,最好不要将空格编码为“+”。
我建议对除 RFC 3986 中定义的“未保留”之外的所有字符进行百分比编码,第 2.3 页
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
实现取决于您选择的编程语言。
如果您的 URL 包含国家字符,请先将它们编码为 UTF-8,然后对结果进行百分比编码。
在这里总结(有些矛盾的)答案,我认为可以归结为:
| standard | + | %20 |
|---------------+-----+-----|
| URL | no | yes |
| query string | yes | yes |
| form params | yes | no |
| mailto query | no | yes |
所以从历史上看,我认为发生的事情是:
RFC 为 URL 的形式及其编码方式指定了一个非常明确的标准。在这种情况下,查询只是一个“字符串”,没有规范应该如何编码键/值对 HTTP 家伙提出了如何在表单参数中编码键/值对的标准,并从 URL 中借用编码标准,除了空格应该编码为+。网友说:很酷,我们有一种编码键/值对的方法,让我们把它放到 URL 查询字符串中
结果:我们最终得到了两种不同的方法来编码 URL 中的空格,具体取决于您正在谈论的部分。但它甚至不违反 URL 标准。从 URL 的角度来看,“查询”只是一个黑盒。如果你想使用除了百分比编码之外的其他编码:把自己搞砸。
但正如电子邮件示例所示,从 URL 查询字符串的 form-params 实现中借用可能会有问题。所以最终使用 %20 更安全,但可能没有开箱即用的库支持。
不定期副业成功案例分享
multipart/form-data
使用 MIME 编码;application/x-www-form-urlencoded
使用+
,正确编码的 URI 使用%20
。http://www.bing.com/search?q=hello+world
和名称中有空格的资源http://camera.phor.net/cameralife/folders/2012/2012-06%20Pool%20party/
mailto:support@example.org?subject=I%20need%20help
。如果您尝试使用 +,电子邮件将使用 +es 而不是空格打开。