URL 的百分比编码差异

Ath*_*ark 1 url encoding utf-8 query-string percent-encoding

在查看了之前关于百分比编码的问题后,我很好奇哪种编码风格是正确的 - 关于百分比编码的维基百科文章暗示使用+而不是%20空格,同时仍然具有application/x-www-urlencoded内容类型。

这让我认为+vs.%20行为取决于 URL 的哪一部分被编码。路径段与查询字符串有何不同?本说明书的细节和参考将不胜感激。


注意:我假设非字母数字字符将通过 UTF-8 进行编码,因为字符的每个八位字节都会变成一个%XX字符串。如果我在这里错了(例如 latin-1 而不是 utf-8),请纠正我,但我对URL 不同部分的编码之间的差异更感兴趣。

Rem*_*eau 5

\n

这让我想到了对比+%20行为取决于 URL 的哪一部分被编码。

\n
\n

它不仅取决于特定的 URL 组件,还取决于该组件填充数据的环境。

\n

\'+\'编码空格字符的使用特定于application/x-www-form-urlencoded格式,适用于在 HTTP 请求中提交的 Web 表单数据。它不适用于 URL 本身。

\n

application/x-www-form-urlencoded格式由 W3C 在 HTML 规范中正式定义。以下是 HTML 4.01 的定义:

\n

第 17.13.3 节处理表单数据,第四步:提交编码的表单数据集

\n
\n

本规范并未指定可与表单一起使用的所有有效提交方法或内容类型。但是,在以下情况下,HTML 4 用户代理必须支持既定约定:

\n

\xe2\x80\xa2如果方法是“get”并且操作是 HTTP URI,则用户代理获取操作的值,在其后面附加“?\”,然后附加表单数据集,使用“编码” application/x-www-form-urlencoded”内容类型。然后,用户代理遍历该 URI 的链接。在这种情况下,表单数据仅限于 ASCII 代码。

\n

\xe2\x80\xa2 如果方法是“post”并且操作是 HTTP URI,则用户代理使用操作属性的值和根据由指定的内容类型创建的消息来执行 HTTP“post”事务。 enctype 属性。

\n
\n

第 17.13.4 节 表单内容类型,application/x-www-form-urlencoded

\n
\n

这是默认的内容类型。使用此内容类型提交的表单必须按如下方式编码:

\n

1.控件名称和值被转义。空格字符被替换为 \'+\',然后保留字符被转义,如 [RFC1738],第 2.2 节中所述:非字母数字字符被替换为 \'%HH\'、一个百分号和两个代表的十六进制数字字符的 ASCII 码。换行符表示为“CR LF”对(即\'%0D%0A\')。

\n

2.控件名称/值按照它们在文档中出现的顺序列出。名称与值之间用“=”分隔,名称/值对之间用“&”分隔。

\n
\n

相应的 HTML5 定义(第 4.10.22.3 节表单提交算法第 4.10.22.6 节 URL 编码的表单数据”)更加精致和详细,但出于本次讨论的目的,其要点大致相同。

\n

GET因此,在通过 HTTP请求而不是请求提交 Web 表单数据的情况下POST,Web 表单数据将使用 URL 进行编码application/x-www-form-urlencoded并按原样放置在 URL 中query组件中。

\n

根据RFC 3986:统一资源标识符 (URI):通用语法

\n
\n

生成 URI 的应用程序应对与保留集中的字符相对应的数据八位字节进行百分比编码,除非 URI 方案特别允许这些字符表示该组件中的数据

\n
\n

\'+\'是保留字符:

\n
reserved    = gen-delims / sub-delims\n\ngen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"\n\nsub-delims  = "!" / "$" / "&" / "\'" / "(" / ")"\n            / "*" / "+" / "," / ";" / "="\n
Run Code Online (Sandbox Code Playgroud)\n

query组件明确允许未编码的\'+\'字符,因为它允许以下字符sub-delims

\n
unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"\n\npct-encoded = "%" HEXDIG HEXDIG\n\npchar       = unreserved / pct-encoded / sub-delims / ":" / "@"\n\nquery       = *( pchar / "/" / "?" )\n
Run Code Online (Sandbox Code Playgroud)\n

因此,在 Web 表单提交的上下文中,空格先使用\'+\'before 进行编码,然后按原样放入query组件中。URL 语法允许这样做,因为 的编码形式application/x-www-form-urlencoded与组件的定义兼容query

\n

因此,例如:http://server/script?field=hello+world

\n

但是,在 Web 表单提交之外,将空格字符直接放入query组件中需要使用pct-encoded,因为\' \'不包含在 或 中unreservedsub-delims并且定义未明确允许query

\n

因此,例如:http://server/script?hello%20world

\n

类似的规则也适用于该path组件,因为它使用了pchar

\n
  path          = path-abempty    ; begins with "/" or is empty\n                / path-absolute   ; begins with "/" but not "//"\n                / path-noscheme   ; begins with a non-colon segment\n                / path-rootless   ; begins with a segment\n                / path-empty      ; zero characters\n\n  path-abempty  = *( "/" segment )\n  path-absolute = "/" [ segment-nz *( "/" segment ) ]\n  path-noscheme = segment-nz-nc *( "/" segment )\n  path-rootless = segment-nz *( "/" segment )\n  path-empty    = 0<pchar>\n  segment       = *pchar\n  segment-nz    = 1*pchar\n  segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )\n                ; non-zero-length segment without any colon ":"\n
Run Code Online (Sandbox Code Playgroud)\n

因此,尽管path允许使用未编码的sub-delims字符,但\'+\'字符会按原样处理,而不是被视为编码的空间。 application/x-www-form-urlencoded不与组件一起使用,因此根据和的定义,path必须对空格字符进行编码。%20pcharsegment-nz-nc

\n

现在,关于用于编码字符的字符集 -

\n

对于 Web 表单提交,该字符集由 Web 表单编码算法(在 HTML5 中比 HTML4 更是如此)中定义的规则决定,该算法用于在将 Web 表单数据插入 URL 之前准备该数据。简而言之,HTML 可以直接在其自身中指定accept-charset属性或隐藏_charset_字段<form>,否则字符集通常是父 HTML 使用的字符集。

\n

然而,在 Web 表单提交之外,没有正式的标准来说明 URL 组件中使用哪种字符集来编码非 ASCII 字符(另一方面,IRI语法需要 UTF-8,尤其是在将 IRI 转换为 URI 时) /网址)。在 IRI 之外,由特定的 URI 方案来规定其字符集(HTTP 方案则不然),否则服务器决定要使用哪个字符集。现在大多数方案/服务器都使用 UTF-8,但仍然有一些服务器/方案使用其他字符集,通常基于服务器的区域设置(Latin1、Shift-JIS 等)。曾尝试直接在 URL 和/或 HTTP 中添加字符集报告(例如确定性 URI 编码\n),但这些并不常用。

\n