在查看this previous SO question regarding percent encoding之后,我很好奇哪种编码样式是正确的 - Wikipedia article on percent encoding暗示使用+
而不是%20
来表示空格,而拥有application/x-www-urlencoded
内容类型。
这使我认为+
与%20
行为取决于URL的哪个部分正在编码。路径段与查询字符串之间有哪些差异?非常感谢本规范的详细信息和参考资料。
注意:我假设非字母数字字符将通过UTF-8编码,因为字符的每个八位字节都变成%XX
字符串。如果我错了,请纠正我(例如latin-1而不是utf-8),但我对URL的不同部分的编码之间的差异更感兴趣。
答案 0 :(得分:3)
这使我认为
+
与%20
行为取决于网址的哪个部分正在编码。
它不仅取决于特定的URL组件,还取决于该组件用数据填充的环境。
使用'+'
编码空格字符特定于application/x-www-form-urlencoded
格式,该格式适用于在HTTP请求中提交的webform数据。它不适用于URL本身。
application/x-www-form-urlencoded
格式由W3C在HTML规范中正式定义。以下是HTML 4.01中的定义:
Section 17.13.3 Processing form data, Step four: Submit the encoded form data set
此规范未指定可与表单一起使用的所有有效提交方法或内容类型。但是,在以下情况下,HTML 4用户代理必须支持已建立的约定:
•如果方法是"得到"并且动作是HTTP URI,用户代理获取动作的值,附加一个`?'然后,附加表格数据集,使用" application / x-www-form-urlencoded"编码。内容类型。用户代理然后遍历指向此URI的链接。在这种情况下,表单数据仅限于ASCII代码。
•如果方法是" post"并且操作是HTTP URI,用户代理进行HTTP" post"使用action属性值的事务和根据enctype属性指定的内容类型创建的消息。
Section 17.13.4 Form content types, application/x-www-form-urlencoded
这是默认内容类型。使用此内容类型提交的表单必须按如下方式编码:
1.控制名称和值被转义。 空格字符替换为' +' ,然后按照[RFC1738]第2.2节中的说明转义保留字符:非字母数字字符替换为'% HH',百分号和两个十六进制数字,表示字符的ASCII码。换行符表示为" CR LF"对(即'%0D%0A')。
2.控件名称/值按它们在文档中出现的顺序列出。通过' ='将名称与值分开。和名称/值对通过'&'
彼此分开
相应的HTML5定义(Section 4.10.22.3 Form submission algorithm和Section 4.10.22.6 URL-encoded form data)更加精致和详细,但为了讨论的目的,jist大致相同。
因此,在通过HTTP GET
请求而不是POST
请求提交webform数据的情况下,使用application/x-www-form-urlencoded
对webform数据进行编码并按原样放置网址query
组件。
每RFC 3986: Uniform Resource Identifier (URI): Generic Syntax:
生成URI的应用程序应对与保留集中的字符对应的数据八位字节进行百分比编码,除非URI方案明确允许这些字符表示该组件中的数据。
'+'
是保留字符:
reserved = gen-delims / sub-delims
gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
query
组件明确允许未编码的'+'
个字符,因为它允许来自sub-delims
的字符:
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
query = *( pchar / "/" / "?" )
因此,在webform提交的上下文中,空格使用'+'
进行编码,然后按原样放入query
组件。 URL语法允许这样做,因为application/x-www-form-urlencoded
的编码形式与query
组件的定义兼容。
所以,例如:http://server/script?field=hello+world
但是,在网络表单提交之外,将空格字符直接放入query
组件需要使用pct-encoded
,因为' '
中不包含unreserved
或sub-delims
,query
定义未明确允许。
所以,例如:http://server/script?hello%20world
类似的规则也适用于path
组件,因为它使用了pchar
:
path = path-abempty ; begins with "/" or is empty
/ path-absolute ; begins with "/" but not "//"
/ path-noscheme ; begins with a non-colon segment
/ path-rootless ; begins with a segment
/ path-empty ; zero characters
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
path-noscheme = segment-nz-nc *( "/" segment )
path-rootless = segment-nz *( "/" segment )
path-empty = 0<pchar>
segment = *pchar
segment-nz = 1*pchar
segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
; non-zero-length segment without any colon ":"
因此,虽然path
允许未编码的sub-delims
个字符,但'+'
个字符会被视为原样,而不是编码空间。 application/x-www-form-urlencoded
组件未使用path
,因此由于%20
和pchar
的定义,空格字符必须编码为segment-nz-nc
。
现在,关于用于编码字符的字符集 -
对于webform提交,该charset由webform编码算法中定义的规则决定(在HTML5中比HTML4更多),用于在将webform数据插入URL之前准备webform数据。简而言之,HTML可以直接在accept-charset
本身中指定_charset_
属性或隐藏<form>
字段,否则字符集通常是父HTML使用的字符集。
但是,在webform提交之外,没有使用charset对URL组件中的非ascii字符进行编码的正式标准(IRI语法,另一方面,需要UTF-8特别是将IRI转换为URI / URL时)。在IRI之外,由特定的URI方案决定它们的字符集(HTTP方案没有),否则服务器决定它想要使用哪个字符集。大多数方案/服务器现在使用UTF-8,但仍有一些服务器/方案使用其他字符集,通常基于服务器的语言环境(Latin1,Shift-JIS等)。尝试直接在URL和/或HTTP中添加字符集报告(例如Deterministic URI Encoding ),但这些并不常用。