简体中文

开发者工具 · URL 编码器和解码器

从 RFC 1738 到 URL 标准:百分比编码规则如何演变

· 背景

url 编码 rfc 历史记录 网络标准

URL 百分比编码标准从 RFC 1738 到 RFC 3986 到 WHATWG URL 标准的演变
原始 ToolAcre 矢量图

自 1994 以来,URL 中的转义字符规则已被重写多次。这篇文章遵循 RFC 1738、RFC 2396、RFC 3986 和 WHATWG URL 标准,并解释了每次更改的内容。

从 RFC 1738 到 URL 标准 - 百分比编码规则如何演变

波形符 (~) 举例说明了编码规则如何在标准生成和部署之间变化。 RFC 1738 (1994) 到处都需要 %7E; RFC 2396 (1998) 将波形符移至未保留位置,允许未编码。 RFC 3986 (2005) 确认未保留状态。带有 %7E 的旧 URL 仍然有效;新建设者输出~。随着网络的成熟和基础设施的标准化,演变反映了部署的经验教训。 RFC 1738 是保守的,因为早期的基础设施是异构且多样的。

RFC 1738 编码 1994 浏览器行为。在 UTF-8 上标准化部署;事实证明限制是不必要的。后来的标准放宽了字符限制。 RFC 3986 允许对非保留字符进行安全解码。

RFC 1738 (1994):“不安全”字符和第一个转义规则 - 什么被认为是危险的以及为什么

RFC 1738 将“不安全”字符定义为与 URI 语法(空格、斜杠)冲突、历史上在协议中使用的字符(控制字符)或系统无法安全传输的字符。保守的列表百分比编码远远超出了现代互联网的需要。许多早期系统早于 RFC;它规范了他们的行为。控制字符在协议中确实很危险;空格是 HTTP 客户端从命令行读取数据时的传输问题。现代系统通过显式编码更优雅地处理这些情况。

针对 RFC 1738 的测试揭示了旧系统的预期。对 20 世纪 90 年代 URL 规范中的字符进行编码,并与现代 RFC 3986 进行比较。差异显示了放松的情况。未保留的集合随着时间的推移而扩大。连字符、句号、下划线始终是安全的。蒂尔德需要 RFC 2396 才能变得安全。保守的方法意味着向后兼容。根据 RFC 1738 规则构建的旧 URL 今天仍然有效。 RFC 3986 部分 6 中的规范化允许安全地解码不必要的百分比编码的非保留字符。

RFC 2396 (1998) — 保留与未保留、通用语法和恢复波浪号

RFC 2396 (1998) 比 RFC 1738 更严格地阐明了字符集。它将服务于 URI 结构的保留字符与作为文字数据的非保留字符形式化。未保留的扩展包括连字符、句点、下划线、波形符。它承认通用 URI 语法与特定于方案的规则分开。 RFC 2396 引入了 gen-delims (:, /, ?, #, [, ], @) 和子 delims (!, $, &, ', (, ), *, +, ,, ;, =) 之间的区别。命名明确了保留字符分为具有不同结构角色的两组。

RFC 2396 引入了规范化指南,指定哪些百分比编码字符可以在不改变含义的情况下进行解码。未保留的字符解码标准化。保留的字符编码棒。 RFC 3986 进一步简化了符号。标准强烈地保持向后兼容性。

RFC 3986 (2005) — ! * ' ( ) 移动到 sub-delims,gen-delims 被命名,规范化指导到达

RFC 3986 (2005) 是百分比编码的现代参考标准。它保留了保留的 /unreserved 区别,但简化了符号并添加了规范化指导。蒂尔德毫不含糊地行动起来。标准澄清的百分比编码的非保留字符可以在不改变含义的情况下进行解码。 RFC 3986 部分 3 精确描述了 URI 语法。 2 节定义字符类别。 6 节专门用于句法规范化的正式规则。如果规范化形式匹配,基于比较的规范化会认为 URI 相同。从路径中删除点段会正常化,但不会发生任何变化。

标准化对于分析、缓存、链接跟踪很重要。仅十六进制数字大小写不同的 URL(RFC 3986 更喜欢大写)在实践中应该是相同的。规范化可防止重复的日志条目和缓存未命中。无论请求者的编码偏好如何,以规范化 URL 为关键的缓存都会提供内容。 RFC 3986 规范化指导使​​系统能够做出一致的决策。但严格的执行会破坏当前互联网上正常工作的 URL。

WHATWG URL 标准:解析浏览器实际接收到的内容 — 编码集、特殊方案和容错

WHATWG URL 标准(2016–现在)是从浏览器体验中产生的,其 URL 不完全遵循 RFC 3986。浏览器面临着未编码的空间、混合编码和怪癖。 WHATWG 描述的是真实的浏览器解析,而不是理论语法。现实世界的浏览器已经制定了实用的规则来容忍空格、处理转义字符、从格式错误的输入中恢复。 RFC 3986 到达 2005 并定义了形式语法,但实践中的浏览器已经略有不同。

WHATWG 定义了九个具有上下文特定规则的编码集。路径中的空格变为 %20; userinfo 中的斜杠变为 %2F。浏览器对网络应用较窄的标准。 RFC 3986 提供基线; WHATWG 以此为基础。

工作示例:一个带有波形符、空格和非 ASCII 字符的 URL — 每代规则如何对其进行编码

国际化域名使用 punycode 编码(München 变为 xn--mnchen-3ya)。路径和查询仍然使用百分比编码。域部分使用punycode;路径和查询部分使用百分比编码。各层不会混合或干扰。

IDNA(应用程序中的国际化域名)解决主机名问题。 Punycode 将非 ASCII 编码为 ASCII 以实现 DNS 兼容性。 xn-- 前缀表示 punycode 编码。算法是确定性的:münchen 总是变成 xn--mnchen-3ya。非 ASCII 字符必须在 DNS 解析之前进行转换。由于 DNS 限制和标签限制,百分比编码不适用于主机名。每种方法都能正确解决不同的问题。标准的单独发展是有充分理由的。

这不包括什么 - IRI 和国际化域名,它们有自己的历史

选择标准取决于上下文。为浏览器构建 URL?遵循 RFC 3986;浏览器应用 WHATWG。较旧的系统?测试实施。了解进化论可以防止混乱。

现代构建者应根据上下文遵循 RFC 3986 或 WHATWG。新旧 URL 共存,需要仔细考虑兼容性。 URL 编码器和解码器始终遵循 RFC 3986,提供独立于浏览器行为的固定参考。 WHATWG 在 RFC 基础知识之外添加了特定于组件的编码集。了解什么时候发生了变化有助于理解系统为何不一致。使用这两种标准测试您的 URL 可以揭示哪个标准在您的环境中进行控制。两个标准都是正确的。

要点:了解您的代码遵循哪个规则手册 — URL 编码器和解码器如何为您提供 RFC 3986 行为作为固定参考点

RFC 3986 规范化允许安全地解码不必要的百分比编码的非保留字符。 %41 规范化为 A。像 %2F 这样的编码保留字符永远不会解码;改变意义会破坏结构。标准机构大力维护向后兼容性。修复问题需要全球范围内的协调,几十年后是不可能的。标准书籍不会追溯破坏网络。改变编码决策会同时破坏数十亿个现有系统。

百分比编码跨越了三十年的精心演变:从 RFC 1738 到 RFC 2396 和 RFC 3986 到现代 WHATWG URL 标准。现代代码应遵循 RFC 3986 基线。具有较早编码的旧 URL 仍然有效。测试往返可确保正确性和兼容性。