在URL中,何时会将空格编码为+
,何时会编码为%20
?
来自维基百科(已添加强调和链接):
当输入到HTML表单中的数据被提交时,表单字段名称和值会被编码并使用GET或POST方法通过HTTP请求消息发送到服务器,或者在历史上通过电子邮件发送。默认情况下使用的编码基于一种非常早期的通用URI百分比编码规则,其中包括若干修改,例如换行符规范化以及将空格替换为“+”而不是“%20”。以这种方式编码的数据的MIME类型是application/x-www-form-urlencoded,并且它目前在HTML和XForms规范中定义(仍然以非常过时的方式定义)。
因此,真正的百分比编码使用%20
,而URL中的表单数据则采用修改后的形式,使用+
。因此,在?
之后的查询字符串中最有可能只看到+
。
这种混淆是因为URL到今天仍然存在问题。
来自一篇博客文章:
以“http://www.google.com”为例。这是一个URL。URL是统一资源定位符,实际上是一个指向网页的指针(在大多数情况下)。自1994年第一次规范以来,URL实际上具有非常明确定义的结构。
我们可以提取关于“http://www.google.com” URL的详细信息:
+---------------+-------------------+
| Part | Data |
+---------------+-------------------+
| Scheme | http |
| Host | www.google.com |
+---------------+-------------------+
如果我们看一个更复杂的URL,比如:
"https://bob:bobby@www.lunatech.com:8080/file;p=1?q=2#third"
我们可以提取以下信息:
+-------------------+---------------------+
| Part | Data |
+-------------------+---------------------+
| Scheme | https |
| User | bob |
| Password | bobby |
| Host | www.lunatech.com |
| Port | 8080 |
| Path | /file;p=1 |
| Path parameter | p=1 |
| Query | q=2 |
| Fragment | third |
+-------------------+---------------------+
https://bob:bobby@www.lunatech.com:8080/file;p=1?q=2#third
\___/ \_/ \___/ \______________/ \__/\_______/ \_/ \___/
| | | | | | \_/ | |
Scheme User Password Host Port Path | | Fragment
\_____________________________/ | Query
| Path parameter
Authority
每个部分的保留字符都不同。
对于HTTP URL,路径片段中的空格必须编码为 "%20"(绝对不是 "+"),而路径片段中的 "+" 字符可以不编码。
现在在查询部分中,空格可以编码为 "+"(出于向后兼容性:不要试图在URI标准中搜索它)或 "%20",而 "+" 字符(由于此模棱两可)必须转义为 "%2B"。
这意味着“blue+light blue”字符串在路径和查询部分必须以不同方式编码:
"http://example.com/blue+light%20blue?blue%2Blight+blue"。
从那里你可以推断出,没有URL结构的语法意识,编码完整构造的URL是不可能的。
总之,你应该在 ?
前面加上 %20
,在后面加上 +
。
?
之前必须使用%20
而不是+
,但在?
之后只是个人口味问题。拜托了,朋友们,请始终使用基于百分号的编码方式,为更重要的事情腾出一些大脑空间吧。 - nydame在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规范中查找有关application/x-www-form-urlencoded的相关段落等。
这是一个URL中的示例字符串,HTML规范允许将空格编码为加号:"http://example.com/over/there?name=foo+bar"。因此,在“?”后面,空格可以被替换为加号。在其他情况下,空格应该被编码为%20。但由于很难正确确定上下文,最好的做法是永远不要将空格编码为“+”。
我建议对除了RFC 3986第2.3节中定义的“未保留字符”以外的所有字符进行百分号编码。
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
%20
。你是在硬编码它们吗?尽管如此,在不同的语言中这并不是很一致。如果我没有记错,在PHP中,urlencode()
将空格视为+
,而Python的urlencode()
将其视为%20
。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()
方法也会将其转换为+
。 - рüффп| standard | + | %20 |
|---------------+-----+-----|
| URL | no | yes |
| query string | yes | yes |
| form params | yes | no |
| mailto query | no | yes |
历史上发生的事情如下:
结果是,在URL的不同部分中,我们有两种不同的编码空格的方式。但这甚至不违反URL标准。从URL的角度来看,“查询”只是一个黑盒子。如果你想使用百分号以外的其他编码方式:自己动手吧。
但正如电子邮件示例所示,从表单参数实现中借鉴URL查询字符串可能会有问题。因此,最终使用%20更加安全,但可能没有现成的库支持。
我很惊讶地发现没有人引用实际的RFC 3986关于“百分号编码”,所以我在这里添加了自己的答案:
由于上述的RFC没有包括将空格编码为+
的任何参考,我猜现在使用%20
是正确的方式。
例如,"%20"是二进制八位组"00100000"(ABNF:%x20)的百分号编码,它在US-ASCII中对应于空格字符(SP)。
multipart/form-data
使用 MIME 编码;application/x-www-form-urlencoded
使用+
,而正确编码的 URI 则使用%20
。 - McDowellhttp://www.bing.com/search?q=hello+world
,同时存在一个名字中包含空格的资源http://camera.phor.net/cameralife/folders/2012/2012-06%20Pool%20party/
。 - William Entrikenmailto:support@example.org?subject=I%20need%20help
。如果您尝试使用+,则会在电子邮件中出现+es而不是空格。 - Sygmoral