目标
URL标准通过以下方法使URL完全互操作:
-
使RFC 3986和RFC 3987与当代实现保持一致,并在此过程中使这些RFC过时。(例如,空格、其他“非法”代码点、查询编码、等同性、规范化,都是尚未完全共享或定义的概念。)URL解析需要像HTML解析一样可靠。[RFC3986] [RFC3987]
-
统一使用术语URL。URI和IRI容易混淆。实际上,两者都使用同一个算法,因此保持它们的区分对任何人都没有帮助。URL也轻松赢得了搜索结果的受欢迎度竞争。
-
详细定义URL现有的JavaScript API,并添加增强功能以使其更易于使用。为URL操作添加一个新的
URL对象,无需使用HTML元素。(这对JavaScript worker环境很有用。) -
确保解析器、序列化器和API的组合保证幂等性。例如,解析-然后-序列化操作的非失败结果在应用进一步的解析-然后-序列化操作时不会改变。同样,通过API操作非失败结果时,应用任何数量的序列化-然后-解析操作也不会改变结果。
随着编辑们对该主题的深入了解,目标的范围可能会有所扩大。
1. 基础设施
本规范依赖于Infra。[INFRA]
本规范中使用的一些术语在以下标准和规范中定义:
- 编码 [ENCODING]
- 文件 API [FILEAPI]
- HTML [HTML]
- Unicode IDNA 兼容性处理 [UTS46]
- Web IDL [WEBIDL]
要序列化一个整数,将其表示为最短的十进制数。
1.1. 写入
验证错误表示输入与有效输入不匹配。鼓励用户代理,尤其是合规性检查器,在某个地方报告它们。
验证错误并不意味着解析器终止。解析器的终止总是明确说明,例如,通过返回语句。
标记验证错误是有用的,因为错误处理可能不直观,遗留的用户代理可能未正确实现错误处理,所写内容的意图对其他开发者可能不清楚。
| 错误类型 | 错误描述 | 失败 |
|---|---|---|
| IDNA | ||
| domain-to-ASCII |
Unicode ToASCII 在 CheckHyphens、 UseSTD3ASCIIRules 和 VerifyDnsLength 均设置为 true 时记录一个错误。[UTS46] 如果记录了关于 Unicode ToASCII 错误的详细信息,鼓励用户代理将其传递下去。 | 是 (当 beStrict 为 true,或者 domain 不是 ASCII 字符串且使用宽松 参数的 Unicode ToASCII 也失败时) |
| 主机解析 | ||
| domain-percent-encoded |
“ | · |
| host-invalid-code-point | 是 | |
| IPv4-empty-part |
一个 IPv4 地址 以 U+002E (.) 结尾。 “ | · |
| IPv4-too-few-parts |
一个 IPv4 地址 的部分少于 4 个。 “ | · |
| IPv4-too-many-parts |
一个 IPv4 地址 的部分多于 4 个。 “ | 是 |
| IPv4-non-numeric-part |
一个 IPv4 地址 部分不是数字。 “ | 是 |
| IPv4-non-decimal-part |
该 IPv4 地址 包含用十六进制或八进制数字表示的数值。 “ | · |
| IPv4-out-of-range-part |
一个 IPv4 地址 部分超过 255。 “ | 是 (仅当适用于最后一个部分时) |
| IPv4-non-ASCII-input |
一个 IPv4 地址 是通过 IDNA 处理从非 ASCII 字符串派生而来的。 “ | · |
| IPv6-unclosed |
一个 IPv6 地址 缺少 右方括号 U+005D (])。 “ | 是 |
| IPv6-invalid-compression |
一个 IPv6 地址 以不恰当的压缩开头。 “ | 是 |
| IPv6-too-many-pieces |
一个 IPv6 地址 包含超过 8 个片段。 “ | 是 |
| IPv6-multiple-compression |
一个 IPv6 地址 在多个位置进行了压缩。 “ | 是 |
| IPv6-invalid-code-point |
一个 IPv6 地址 包含一个既不是 ASCII 十六进制数字 也不是 U+003A (:) 的码点。或者它意外结束。 | 是 |
| IPv6-too-few-pieces |
一个未压缩的 IPv6 地址包含少于 8 个片段。 “ | 是 |
| IPv6-piece-leading-zero |
一个 IPv6 地址 片段 包含前导 U+0030 (0)。 “ | · |
| IPv4-in-IPv6-too-many-pieces |
一个带有 IPv4 地址语法的 IPv6 地址:该 IPv6 地址有超过 6 个片段。 “ | 是 |
| IPv4-in-IPv6-invalid-code-point |
“ “ “ “ “ | 是 |
| IPv4-in-IPv6-out-of-range-part |
一个带有 IPv4 地址语法的 IPv6 地址:一个 IPv4 部分超过 255。 “ | 是 |
| IPv4-in-IPv6-too-few-parts |
一个带有 IPv4 地址语法的 IPv6 地址:一个 IPv4 地址包含 的部分过少。 “ | 是 |
| URL 解析 | ||
| invalid-URL-unit |
发现了一个不是 URL 单元的码点。 | · |
| special-scheme-missing-following-solidus |
输入的 scheme 后面没有跟着“ | · |
| missing-scheme-non-relative-URL |
输入缺少一个 scheme,因为它不是以 ASCII 字母开头,并且要么未提供 base URL,要么该 base URL 不能 用作 base URL,因为它有一个不透明路径。 | 是 |
| invalid-reverse-solidus |
该 URL 具有特殊 scheme,并且它使用 U+005C (\) 而不是 U+002F (/)。 “ | · |
| invalid-credentials |
输入包含凭据。 “ “ | · |
| host-missing | 是 | |
| port-out-of-range |
输入的端口过大。 “ | 是 |
| port-invalid |
输入的端口无效。 “ | 是 |
| file-invalid-Windows-drive-letter |
输入是一个relative-URL 字符串,它以 Windows 驱动器盘符开头,
并且
base
URL 的 scheme 是“
| · |
| file-invalid-Windows-drive-letter-host |
一个 | · |
1.2. 解析器
EOF 代码点是一个概念性的代码点,表示字符串或代码点流的结束。
对于一个字符串输入,指针是一个整数,指向输入中的代码点。最初它指向输入的开始。如果它为-1,则表示没有指向。如果它大于或等于输入的代码点长度,则指向EOF代码点。
当使用指针时,c引用指针指向的代码点,只要它没有指向空处。当指针指向空处时,c无法使用。
当使用指针时,remaining引用从指针+1到字符串末尾的代码点子串,只要c不是EOF代码点。当c是EOF代码点时,remaining无法使用。
如果"mailto:username@example"是正在处理的字符串,并且指针指向@,c是U+0040 (@),而remaining是"example"。
如果正在处理的是空字符串,并且指针指向开始然后减1,使用c或remaining将会出错。
1.3. 百分比编码字节
一个 百分号编码 字节 是一个由 U+0025 (%) 后跟两个 ASCII 十六进制数字组成的字符串。
通常,一个由 百分号编码字节组成的序列,最好满足这样的条件: 当它们被百分号解码后,再传给 无 BOM 的 UTF-8 解码或失败时,不会最终 变成失败。这一点有多重要, 取决于这些 百分号编码字节被用在哪里。例如,对于 host 解析器来说,不 遵循此建议是致命的;而对于 URL 渲染, 百分号编码 字节则不会以百分号解码后的形式被渲染。
要百分比编码一个字节byte,返回由U+0025 (%),后跟表示byte的两个ASCII大写十六进制数字组成的字符串。
要百分比解码一个字节序列input,请按以下步骤操作:
当input包含非ASCII字节时,使用除UTF-8解码,无BOM外的任何内容都可能不安全,不推荐使用。
要百分比解码一个标量值字符串input:
通常,百分比编码会产生包含更多U+0025 (%)代码点的字符串,而百分比解码则会产生包含较少0x25 (%)字节的字节序列。
C0 控制百分号编码集 是一个 百分号编码集,包含 C0 控制字符及所有大于 U+007E (~) 的 码点。
片段百分号编码集 是一个 百分号编码集,包含 C0 控制百分号编码集、U+0020 空格、U+0022 (")、U+003C (<)、U+003E (>) 以及 U+0060 (`)。
查询百分号编码集 是一个 百分号编码集,包含 C0 控制百分号编码集和 U+0020 空格、U+0022 (")、U+0023 (#)、U+003C (<)、U+003E (>)。
查询百分号编码集无法用 片段百分号编码集来定义,因为 U+0060 (`) 被省略了。
特殊查询百分号编码集 是一个 百分号编码集, 包含 查询 百分号编码集和 U+0027 (')。
路径百分号编码集 是一个 百分号编码集, 包含 查询百分号编码集及 U+003F (?)、U+005E (^)、U+0060 (`)、 U+007B ({) 和 U+007D (})。
用户信息百分号编码集 是一个 百分号编码集, 包含 路径百分号编码集和 U+002F (/)、U+003A (:)、U+003B (;)、U+003D (=)、U+0040 (@)、U+005B ([) 到 U+005D (])(含),以及 U+007C (|)。
组件 百分号编码集 是一个 百分号编码集, 包含 用户信息百分号编码集和 U+0024 ($) 到 U+0026 (&)(含)、U+002B (+) 以及 U+002C (,)。
这由 HTML 的
registerProtocolHandler()使用,
也可以被其它标准采用,
百分号编码后的数据可以嵌入到 URL 的 路径、
查询或片段部分,或在
不透明主机名中。配合
UTF-8
百分号编码使用,结果与 JavaScript 的
encodeURIComponent() [sic] 完全一致。[HTML] [ECMA-262]
application/x-www-form-urlencoded
百分号编码集 是一个
百分号编码集,
包含 组件百分号编码集和 U+0021 (!)、
U+0027 (') 到 U+0029 右括号(含),以及 U+007E (~)。
application/x-www-form-urlencoded
百分号编码集包含了
除 ASCII 字母数字、U+002A (*)、U+002D (-)、U+002E (.) 和
U+005F (_) 以外的所有码点。
要编码后百分号编码,需传入 编码 encoding,标量值字符串 input,和 百分号编码集 percentEncodeSet:
-
断言:encoding 为 UTF-8 或 percentEncodeSet 是 特殊查询百分号编码集 或
application/x-www-form-urlencoded百分号编码集。 -
如果 percentEncodeSet 是
application/x-www-form-urlencoded百分号编码集,则令 spaceAsPlus 为 true,否则为 false。 -
令 encoder 为从 encoding 获取的编码器结果。
-
令 inputQueue 为 input 转换为 I/O 队列。
-
令 output 为空字符串。
-
令 potentialError 为 0。
需要非 null 值以进入随后 while 循环。
-
当 potentialError 非 null 时:
-
返回 output。
在 percentEncodeSet 可能取的值中,只有两个会对 U+0025 (%) 编码,因此可实现“可还原的数据”:组件
百分号编码集和
application/x-www-form-urlencoded
百分号编码集。其它值(常被URL 解析器
使用)不会处理 U+0025 (%),因此首先需对其做
UTF-8 百分号编码,
才能正确表示。
要对 标量值 scalarValue用 percentEncodeSet 做UTF-8 百分号编码,返回以 编码后百分号编码配合 UTF-8、 scalarValue 作为 字符串,以及 percentEncodeSet 得到的结果。
要对 标量值字符串 input 用 percentEncodeSet 做 UTF-8 百分号编码,返回以 编码后百分号编码配合 UTF-8、 input 以及 percentEncodeSet 的结果。
以下是上文定义的操作的举例总结:
| 操作 | 输入 | 输出 |
|---|---|---|
| 百分号编码 input | 0x23 | "%23"
|
| 0x7F | "%7F"
| |
| 百分号解码 input | `%25%s%1G`
| `%%s%1G`
|
| 字符串百分号解码 input | "‽%25%2E"
| 0xE2 0x80 0xBD 0x25 0x2E |
| 编码后百分号编码 使用 Shift_JIS、 input,和 特殊查询百分号编码集 | " "
| "%20"
|
"≡"
| "%81%DF"
| |
"‽"
| "%26%238253%3B"
| |
| 编码后百分号编码 使用 ISO-2022-JP、input, 以及 特殊查询百分号编码集 | "¥"
| "%1B(J\%1B(B"
|
编码后百分号编码
使用 Shift_JIS、input 和
application/x-www-form-urlencoded
百分号编码集
| "1+1 ≡ 2%20‽"
| "1%2B1+%81%DF+2%2520%26%238253%3B"
|
| UTF-8 百分号编码 input,使用 用户信息百分号编码集 | U+2261 (≡) | "%E2%89%A1"
|
| U+203D (‽) | "%E2%80%BD"
| |
| UTF-8 百分号编码 input 使用 用户信息百分号编码集 | "Say what‽"
| "Say%20what%E2%80%BD"
|
2. 安全注意事项
URL的安全性取决于其环境。在呈现、解释和传递URL时需格外小心。
在呈现和分配新的URL时,需要考虑“欺骗”。这种攻击方式可能会让一个主机或URL与另一个混淆。例如,考虑如何1/l/I、m/rn/rri、0/O和а/a看起来都非常相似。更糟糕的是,考虑U+202A LEFT-TO-RIGHT EMBEDDING以及类似的代码点是不可见的。[UTR36]
在将URL从A传递给B时,双方都需要仔细考虑发生的情况。A可能会泄露它不希望泄露的数据。B可能会接收到意料之外的输入,并采取对用户有害的行动。尤其是,B永远不应信任A,因为在某些情况下,来自A的URL可能来自不受信任的来源。
3. 主机 (域名和IP地址)
在高层次上,主机、有效主机字符串、主机解析器和主机序列化器的关系如下:
-
主机可以被视为内存中的表示。
根据提供给主机解析器的isOpaque参数,解析-序列化往返操作会产生以下结果:
| 输入 | 输出 (isOpaque = false) | 输出 (isOpaque = true) |
|---|---|---|
EXAMPLE.COM |
example.com (域名) |
EXAMPLE.COM (不透明主机) |
example%2Ecom |
example%2Ecom (不透明主机) |
|
faß.example |
xn--fa-hia.example (域名) |
fa%C3%9F.example (不透明主机) |
0 |
0.0.0.0 (IPv4) |
0 (不透明主机) |
%30 |
%30 (不透明主机) |
|
0x |
0x (不透明主机) |
|
0xffffffff |
255.255.255.255 (IPv4) |
0xffffffff (不透明主机) |
[0:0::1] |
[::1] (IPv6) |
|
[0:0::1%5D] |
失败 | |
[0:0::%31] |
||
09 |
失败 | 09 (不透明主机) |
example.255 |
example.255 (不透明主机) |
|
example^example |
失败 | |
3.1. 主机表示
主机是一个域名、IP 地址、不透明主机或空主机。通常,主机用作网络地址,但有时在URL中用作不需要网络地址的不透明标识符。
典型的 URL 其主机为 不透明主机 的例子为
git://github.com/whatwg/url.git。
下文引用的 RFC 仅供参考,对 主机 的编写、解析和序列化没有影响,除非在以下章节中另有说明。
域名是一个非空的ASCII 字符串,用于标识网络中的领域。[RFC1034]
域标签是域名 domain 上通过 严格拆分 U+002E (.) 得到的结果。
example.com 和 example.com. 这两个域名并不相同,通常被视为不同的域名。
一个 IPv4 地址是一个32 位无符号整数,用于标识网络地址。 [RFC791]
一个 IPv6 地址是一个128 位无符号整数,用于标识网络地址。该整数由 8 个 16 位无符号整数组成的列表构成,也称为 IPv6 地址的片段。 [RFC4291]
对 <zone_id> 的支持是故意省略的。
不透明主机是一个非空的ASCII 字符串,可以用于进一步处理。
空主机是一个空字符串。
3.2. 主机杂项
禁止的主机代码点是 U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR, U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>), U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), 或 U+007C (|)。
禁止的域名代码点是禁止的主机代码点、C0 控制、U+0025 (%) 或 U+007F DELETE。
| 主机输入 | 公共后缀 | 可注册域名 |
|---|---|---|
com
| com
| null |
example.com
| com
| example.com
|
www.example.com
| com
| example.com
|
sub.www.example.com
| com
| example.com
|
EXAMPLE.COM
| com
| example.com
|
example.com.
| com.
| example.com.
|
github.io
| github.io
| null |
whatwg.github.io
| github.io
| whatwg.github.io
|
إختبار
| xn--kgbechtv
| null |
example.إختبار
| xn--kgbechtv
| example.xn--kgbechtv
|
sub.example.إختبار
| xn--kgbechtv
| example.xn--kgbechtv
|
[2001:0db8:85a3:0000:0000:8a2e:0370:7334]
| null | null |
规范应优先考虑源概念进行安全决策。“公共后缀”和“可注册域名”的概念不能作为提供硬性安全边界的依据,因为公共后缀列表会因客户端而有所不同。忽略此建议的规范应仔细考虑是否应将 URL 的方案纳入任何决策中,即是否应使用 同一站点或无方案同一站点的概念。
3.3. IDNA
domain 解析器算法,给定一个 标量值字符串 domain 和一个布尔值 beStrict,运行以下 步骤。它们返回失败或一个 domain。
-
令 strictResult 为使用 domain 和 true 运行 domain 解析器 ToASCII 的结果。
-
如果 strictResult 是失败值,则发生 domain-to-ASCII 验证 错误。此步骤不会返回。
-
如果 beStrict 为 true:
-
如果 strictResult 是失败值,则返回失败。
-
返回 strictResult。
-
-
令 result 为 null。
-
如果 domain 是一个 ASCII 字符串,则将 result 设置为 domain 的小写化结果。
当 beStrict 为 false 且 domain 是一个 ASCII 字符串时, 由于 Web 兼容性,无论 Unicode ToASCII 的结果如何,该算法都会返回 domain 的小写化结果。 IgnoreInvalidPunycode 本身并不足够,因为 Punycode 可以成功解码, 但仍然不满足有效性标准。例如,
xn--8i7caa解码为www, 其码点的状态为“mapped”。[UTS46] -
否则:
-
将 result 设置为使用 domain 和 false 运行 domain 解析器 ToASCII 的结果。
-
如果 result 是失败值,则返回失败。
-
-
如果 result 是空字符串,则返回失败。
-
如果 result 包含一个 禁止的 domain 码点,则返回 失败。
由于 Web 兼容性以及与非基于 DNS 的系统兼容, 禁止的 domain 码点是 UseSTD3ASCIIRules 为 true 时不允许的码点的一个子集。另见 issue #397。
-
返回 result。
本文档以及整个 Web 平台使用
Unicode IDNA Compatibility Processing,而不是 IDNA2008。例如,
☕.example 会变成 xn--53h.example,而不是失败。[UTS46] [RFC5890]
domain 解析器 ToASCII算法,给定一个 标量 值字符串 domain 和一个布尔值 beStrict,返回运行 Unicode ToASCII 的结果,其中 domain_name 设置为 domain, CheckHyphens 设置为 beStrict,CheckBidi 设置为 true,CheckJoiners 设置为 true,UseSTD3ASCIIRules 设置为 beStrict,Transitional_Processing 设置为 false,VerifyDnsLength 设置为 beStrict,且 IgnoreInvalidPunycode 设置为 false。[UTS46]
domain 转 Unicode算法,给定一个 domain domain,运行以下步骤:
-
令 result 为运行 Unicode ToUnicode 的结果,其中 domain_name 设置为 domain, CheckHyphens 设置为 false,CheckBidi 设置为 true,CheckJoiners 设置为 true, UseSTD3ASCIIRules 设置为 false,Transitional_Processing 设置为 false,且 IgnoreInvalidPunycode 设置为 false。[UTS46]
-
如果记录了错误,则返回 domain。
因为 domain 只能由 host 解析器产生,所以任何已记录的 错误都已经表示为验证错误。返回 domain 可确保 domain 解析器和 domain 转 Unicode 在诸如
xn--8i7caa这样的输入上能够往返转换。 -
返回 result。
3.4. 主机编写
一个 有效主机字符串必须是一个有效域名字符串、一个 有效 IPv4 地址字符串,或者:U+005B ([),后跟一个 有效 IPv6 地址字符串,再后跟 U+005D (])。
一个字符串 input 是一个有效 域名,如果这些步骤返回 true:
-
令 domain 为使用 input 和 true 运行域解析器的结果。
-
如果 domain 是失败,则返回 false。
-
如果在 domain 上运行以数字结尾检查器返回 true,则 返回 false。
-
返回 true。
理想情况下,我们根据组成一个 有效域的一系列码点来定义它,而不是通过 打地鼠式的方式: issue 245。
有效域字符串必须是一个作为 有效域的字符串。
有效 IPv4 地址字符串必须是四个尽可能短的 ASCII 数字字符串,表示 0 到 255 范围内的十进制数, 包含端点,彼此之间由 U+002E (.) 分隔。
有效 IPv6 地址字符串必须是下列之一:
-
一个有效 IPv6 片段字符串,其有效片段长度为 8。
-
一个有效 IPv6 片段和 IPv4 字符串,其有效片段长度为 8。
-
U+003A U+003A (::),可选地前接一个有效 IPv6 片段字符串,并且 可选地后接一个有效 IPv6 片段字符串或一个 有效 IPv6 片段和 IPv4 字符串,使得 前接和后接字符串的有效片段长度 之和至多为 7。
有效 IPv6 片段和 IPv4 字符串是一个有效 IPv6 片段字符串, 后跟 U+003A (:),再后跟一个有效 IPv4 地址字符串;或者单独一个 有效 IPv4 地址字符串。
有效 IPv6 片段 字符串是一个或多个有效 IPv6 片段字符串,彼此之间由 U+003A (:) 分隔。
有效 IPv6 片段 字符串是一个尽可能短的 ASCII 十六进制 数字字符串, 表示 0 到 0xFFFF 范围内的十六进制数,包含端点。
一个有效 IPv6 片段字符串的有效片段 长度是它所包含的 有效 IPv6 片段字符串的数量。一个 有效 IPv6 片段和 IPv4 字符串的有效片段长度是它 所包含的有效 IPv6 片段字符串的数量, 再加 2。
这是从 A Recommendation for IPv6 Address Text Representation 派生而来的。为了与 IPv4 保持一致, 不允许前导零。[RFC5952]
有效不透明主机 字符串必须是下列之一:
-
U+005B ([),后跟一个有效 IPv6 地址字符串,再后跟 U+005D (])。
这不是有效主机字符串定义的一部分,因为它需要上下文 才能区分。
3.5. 主机解析
主机解析器接受一个 标量值字符串 input,以及一个可选布尔值 isOpaque(默认为 false),然后运行这些步骤。它们返回失败或一个主机。
-
如果 input 以 U+005B ([) 开头,则:
-
如果 input 不是以 U+005D (]) 结尾,IPv6-unclosed 验证错误,返回失败。
-
返回对移除其前导 U+005B ([) 和尾随 U+005D (]) 后的 input 进行 IPv6 解析的结果。
-
-
如果 isOpaque 为 true,则返回对 input 进行 不透明主机解析的结果。
-
断言:input 不是空字符串。
-
如果 input 包含百分比编码字节, domain-percent-encoded 验证错误。
-
令 domain 为在 input 的 百分比解码上运行 无 BOM 的 UTF-8 解码的结果。
或者也可以使用无 BOM 的 UTF-8 解码或失败, 并结合在失败时提前返回,因为域解析器会在 U+FFFD (�) 上失败。
-
令 asciiDomain 为使用 domain 和 false 运行 域解析器的结果。
-
如果 asciiDomain 为失败,则返回失败。
-
如果 asciiDomain 以数字结尾:
-
如果 domain 不是ASCII 字符串,IPv4-non-ASCII-input 验证错误。
-
返回对 asciiDomain 进行 IPv4 解析的结果。
-
-
返回 asciiDomain。
以数字结尾 检查器接受一个ASCII 字符串 input,然后 运行这些步骤。它们返回一个布尔值。
IPv4 解析器 接受一个ASCII 字符串 input ,然后运行这些步骤。它们返回失败或一个 IPv4 地址。
IPv4 解析器不应被直接调用。相反,应检查 主机解析器的返回值是否为一个 IPv4 地址。
-
令 parts 为在 U+002E (.) 上严格 拆分 input 的结果。
-
如果 parts 中的最后一个项目是空字符串,则:
-
如果 parts 的大小小于 4,IPv4-too-few-parts 验证 错误。
-
如果 parts 的大小大于 4,IPv4-too-many-parts 验证 错误,返回失败。
-
令 numbers 为空列表。
-
对 parts 的每个 part 执行:
-
令 result 为解析 part 的结果。
-
如果 result 为失败,IPv4-non-numeric-part 验证错误, 返回失败。
-
如果 result[1] 为 true,IPv4-non-decimal-part 验证错误。
-
将 result[0] 追加到 numbers。
-
-
如果 numbers 中的任何项目大于 255,IPv4-out-of-range-part 验证 错误。
-
如果 numbers 中除最后一个项目外的任何项目大于 255,则 返回失败。
-
令 ipv4 为 numbers 中的最后一个项目。
-
令 counter 为 0。
-
对 numbers 的每个 n 执行:
-
将 ipv4 增加 n × 256(3 − counter)。
-
将 counter 增加 1。
-
-
返回 ipv4。
IPv4 数字 解析器接受一个ASCII 字符串 input,然后运行 这些步骤。它们返回失败或一个由数字和布尔值组成的元组。
-
如果 input 是空字符串,则返回失败。
-
令 validationError 为 false。
-
令 R 为 10。
-
如果 input 包含至少两个码点,且前两个码点是 “
0X”或“0x”,则:-
将 validationError 设为 true。
-
从 input 中移除前两个码点。
-
将 R 设为 16。
-
-
否则,如果 input 包含至少两个码点,且第一个码点是 U+0030 (0),则:
-
将 validationError 设为 true。
-
从 input 中移除第一个码点。
-
将 R 设为 8。
-
-
如果 input 是空字符串,则返回 (0, true)。
-
如果 input 包含不是 radix-R 数字的码点,则 返回失败。
-
令 output 为 input 以 radix-R 记法表示的数学整数值, 其中对值为 0 到 15 的数字使用 ASCII 十六进制数字。
-
返回 (output, validationError)。
IPv6 解析器 接受一个标量值字符串 input,然后运行这些步骤。它们返回失败或一个 IPv6 地址。
从理论上讲,IPv6 解析器可以被直接调用,但实际这样做之前请先与 本文档的编辑讨论。
-
令 pieceIndex 为 0。
-
令 compress 为 null。
-
令 pointer 为 input 的一个指针。
-
如果 c 是 U+003A (:),则:
-
如果 remaining 不是 以 U+003A (:) 开头,IPv6-invalid-compression 验证错误,返回失败。
-
将 pointer 增加 2。
-
将 pieceIndex 增加 1,然后将 compress 设为 pieceIndex。
-
-
-
如果 pieceIndex 为 8,IPv6-too-many-pieces 验证错误, 返回失败。
-
如果 c 是 U+003A (:),则:
-
如果 compress 非 null,IPv6-multiple-compression 验证错误,返回失败。
- 将 pointer 和 pieceIndex 增加 1,将 compress 设为 pieceIndex,然后继续。
-
-
令 value 和 length 为 0。
-
当 length 小于 4 且 c 是 ASCII 十六进制数字时,将 value 设为 value × 0x10 + 被解释为十六进制数的 c, 并将 pointer 和 length 增加 1。
-
如果 c 是 U+002E (.),则:
-
如果 length 为 0,IPv4-in-IPv6-invalid-code-point 验证错误,返回失败。
-
将 pointer 减少 length。
-
如果 pieceIndex 大于 6,IPv4-in-IPv6-too-many-pieces 验证错误,返回失败。
-
令 numbersSeen 为 0。
-
-
令 ipv4Piece 为 null。
-
如果 numbersSeen 大于 0,则:
-
如果 c 是 U+002E (.) 且 numbersSeen 小于 4,则将 pointer 增加 1。
- 否则,IPv4-in-IPv6-invalid-code-point 验证错误,返回 失败。
-
-
如果 c 不是 ASCII 数字,IPv4-in-IPv6-invalid-code-point 验证错误,返回 失败。
-
-
令 number 为被解释为十进制数的 c。
-
如果 ipv4Piece 为 null,则将 ipv4Piece 设为 number。
-
否则,如果 ipv4Piece 为 0,IPv4-in-IPv6-invalid-code-point 验证错误,返回 失败。
-
否则,将 ipv4Piece 设为 ipv4Piece × 10 + number。
-
如果 ipv4Piece 大于 255,IPv4-in-IPv6-out-of-range-part 验证错误,返回 失败。
-
将 pointer 增加 1。
-
-
将 address[pieceIndex] 设为 address[pieceIndex] × 0x100 + ipv4Piece。
-
将 numbersSeen 增加 1。
-
如果 numbersSeen 为 2 或 4,则将 pieceIndex 增加 1。
-
-
如果 numbersSeen 不是 4,IPv4-in-IPv6-too-few-parts 验证错误,返回失败。
-
跳出。
-
-
否则,如果 c 是 U+003A (:):
-
将 pointer 增加 1。
-
如果 c 是 EOF 码点,IPv6-invalid-code-point 验证错误,返回失败。
-
-
否则,如果 c 不是 EOF 码点, IPv6-invalid-code-point 验证错误,返回失败。
-
如果 length 大于 1 且 value 小于 0x10length − 1,IPv6-piece-leading-zero 验证 错误。
-
将 address[pieceIndex] 设为 value。
-
将 pieceIndex 增加 1。
-
-
如果 compress 非 null,则:
-
令 swaps 为 pieceIndex − compress。
-
将 pieceIndex 设为 7。
-
当 pieceIndex 不是 0 且 swaps 大于 0 时,交换 address[pieceIndex] 与 address[compress + swaps − 1],然后将 pieceIndex 和 swaps 都减少 1。
-
-
否则,如果 compress 为 null 且 pieceIndex 不是 8, IPv6-too-few-pieces 验证错误,返回 失败。
-
返回 address。
不透明主机 解析器接受一个 标量值字符串 input,然后运行这些 步骤。它们返回失败或一个 不透明主机。
-
如果 input 包含被禁止的主机码点, host-invalid-code-point 验证错误,返回 失败。
-
如果 input 包含一个既不是 码点 URL 码点也不是 U+0025 (%) 的码点,invalid-URL-unit 验证错误。
-
如果 input 包含一个 U+0025 (%),且其后的两个码点 不是 ASCII 十六进制数字,invalid-URL-unit 验证 错误。
-
返回在 input 上使用 C0 控制百分比编码集运行 UTF-8 百分比编码的结果。
3.6. 主机序列化
IPv6 序列化器接受一个 IPv6 地址 address,然后运行这些步骤。它们返回一个 ASCII 字符串。
-
令 output 为空字符串。
-
令 compress 为给定 address 后 查找 IPv6 地址 压缩片段索引的结果。
-
令 ignore0 为 false。
-
对 address 的 片段的 索引中的每个 pieceIndex 执行:
-
如果 ignore0 为 true 且 address[pieceIndex] 为 0,则 继续。
-
否则,如果 ignore0 为 true,则将 ignore0 设为 false。
-
如果 compress 是 pieceIndex,则:
-
如果 pieceIndex 为 0,则令 separator 为“
::”; 否则为 U+003A (:)。 -
将 separator 追加到 output。
-
将 ignore0 设为 true,并继续。
-
-
将 address[pieceIndex] 以尽可能短的小写十六进制数表示, 并追加到 output。
-
如果 pieceIndex 不是 7,则将 U+003A (:) 追加到 output。
-
-
返回 output。
此算法要求采用 A Recommendation for IPv6 Address Text Representation 中的建议。 [RFC5952]
要在给定一个 IPv6 地址 address 的情况下查找 IPv6 地址压缩片段索引:
-
令 longestIndex 为 null。
-
令 longestSize 为 1。
-
令 foundIndex 为 null。
-
令 foundSize 为 0。
-
对于 address 的 片段的 索引中的每个 pieceIndex 执行:
-
如果 address 的片段[pieceIndex] 不是 0:
-
如果 foundSize 大于 longestSize,则将 longestIndex 设为 foundIndex,并将 longestSize 设为 foundSize。
- 将 foundIndex 设为 null。
- 将 foundSize 设为 0。
-
-
否则:
-
如果 foundIndex 为 null,则将 foundIndex 设为 pieceIndex。
-
将 foundSize 增加 1。
-
-
-
如果 foundSize 大于 longestSize,则返回 foundIndex。
-
返回 longestIndex。
3.7. 主机等效性
证书比较需要一个忽略域名末尾点(如果有的话)的主机等效性检查。然而,这些主机还强制执行了诸如DNS长度等其他方面的验证,而这些在此处未强制执行,因为URL不强制执行它们。如果有人对如何将这两者更紧密结合,或什么是好的统一模型有好的建议,请提交问题。
4. URL
从高层来看,一个 URL、有效 URL 字符串、URL 解析器和 URL 序列化器之间的关系如下:
-
一个 URL 可被视为 内存中表示。
-
一个有效 URL 字符串定义了什么样的输入在给到 URL 解析器时不会触发验证错误或 失败。即,会被视为符合规范或 有效的输入。
-
URL 序列化器接受一个 URL,并返回一个 ASCII 字符串。 (如果 随后对该字符串进行解析,结果将等于被序列化的那个 URL。)URL 序列化器的输出 并不总是一个有效 URL 字符串。
| 输入 | 基准 | 有效 | 输出 |
|---|---|---|---|
https:example.org
| ❌ | https://example.org/
| |
https://////example.com///
| ❌ | https://example.com///
| |
https://example.com/././foo
| ✅ | https://example.com/foo
| |
hello:world
| https://example.com/
| ✅ | hello:world
|
https:example.org
| https://example.com/
| ❌ | https://example.com/example.org
|
\example\..\demo/.\
| https://example.com/
| ❌ | https://example.com/demo/
|
example
| https://example.com/demo
| ✅ | https://example.com/example
|
file:///C|/demo
| ❌ | file:///C:/demo
| |
..
| file:///C:/demo
| ✅ | file:///C:/
|
file://localhost/
| ✅ | file:///
| |
file://loc%61lhost/
| ❌ | file:///
| |
https://user:[email protected]/
| ❌ | https://user:[email protected]/
| |
https://example.org/foo bar
| ❌ | https://example.org/foo%20bar
| |
https://EXAMPLE.com/../x
| ✅ | https://example.com/x
| |
https://ex ample.org/
| ❌ | 失败 | |
example
| ❌,由于缺少基准 | 失败 | |
https://example.com:demo
| ❌ | 失败 | |
http://[www.example.com]/
| ❌ | 失败 | |
https://example.org//
| ✅ | https://example.org//
| |
https://example.com/[]?[]#[]
| ❌ | https://example.com/[]?[]#[]
| |
https://example/%?%#%
| ❌ | https://example/%?%#%
| |
https://example/%25?%25#%25
| ✅ | https://example/%25?%25#%25
|
4.1. URL 表示
一个 URL 是一个结构体,它 表示一个通用标识符。为与有效 URL 字符串区分开来,它也可以 被称为 URL 记录。
一个 URL 的 scheme 是一个 ASCII 字符串,用于标识 URL 的类型,并可在解析后用于 分派一个 URL 以进行进一步 处理。 它最初是空字符串。
一个 URL 的 username 是一个 ASCII 字符串,用于标识用户名。它最初是空字符串。
一个 URL 的 password 是一个 ASCII 字符串,用于标识密码。它最初是空字符串。
一个 URL 的 host 是 null 或一个 主机。它最初为 null。
下表列出了允许的 URL 的 scheme / host 组合。
| scheme | host | |||||
|---|---|---|---|---|---|---|
| 域 | IPv4 地址 | IPv6 地址 | 不透明主机 | 空主机 | null | |
除 "file" 外的特殊
scheme
| ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
"file"
| ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| 其他 | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
一个 URL 的 port 是 null 或一个 16 位无符号整数,用于标识一个网络端口。它 最初为 null。
一个 URL 的 path 是一个 URL 路径,通常用于标识一个 位置。它最初是 « »。
一个特殊的 URL 的 path 始终是一个 列表,即它 从不是不透明的。
一个 URL 的 query 要么是 null,要么是一个 ASCII 字符串。它最初为 null。
一个 URL 的 fragment 要么是 null,要么是 一个 ASCII 字符串,可用于对该 URL 的其他组件所标识的资源进行进一步处理。 它最初为 null。
一个 URL 还具有关联的 blob URL 条目,它要么是 null,要么是一个 blob URL 条目。它最初为 null。
这用于支持缓存一个 "blob" URL 所引用的对象及其
源。缓存这些内容很重要,因为在解析与获取之间,该 URL 可能会从
blob
URL 存储中移除,而获取仍然
需要成功。
下表列出了有效 URL 字符串在被解析时如何映射 到一个 URL 的组件。Username、password 和 blob URL 条目被省略;在下面的示例中,它们分别是空字符串、 空字符串和 null。
| 输入 | Scheme | Host | Port | Path | Query | Fragment |
|---|---|---|---|---|---|---|
https://example.com/
| "https"
| "example.com"
| null | « 空字符串 » | null | null |
https://localhost:8000/search?q=text#hello
| "https"
| "localhost"
| 8000 | « "search" »
| "q=text"
| "hello"
|
urn:isbn:9780307476463
| "urn"
| null | null | "isbn:9780307476463"
| null | null |
file:///ada/Analytical%20Engine/README.md
| "file"
| 空字符串 | null | « "ada", "Analytical%20Engine", "README.md" »
| null | null |
URL 路径要么是一个 URL 路径片段,要么是一个由零个 或多个 URL 路径 片段组成的列表。
URL 路径片段是一个 ASCII 字符串。它通常指代一个 目录或文件,但没有预定义含义。
一个
单点 URL 路径片段
是一个 URL 路径片段,
它是 ".",或者是与 "%2e" ASCII
大小写不敏感
匹配的字符串。
一个
双点 URL 路径片段
是一个 URL 路径片段,
它是 "..",或者是与 ".%2e"、"%2e." 或
"%2e%2e" ASCII
大小写不敏感
匹配的字符串。
4.2. URL 杂项
特殊 scheme 是一个ASCII 字符串,它列在下表第一列中。 特殊 scheme 的 默认端口列在 同一行的第二列中。任何其他 默认端口 ASCII 字符串 是 null。
| 特殊方案 | 默认端口 |
|---|---|
"ftp"
| 21 |
"file"
| null |
"http"
| 80 |
"https"
| 443 |
"ws"
| 80 |
"wss"
| 443 |
URL 是特殊的,如果它的方案是特殊方案。URL不是特殊的,如果它的方案不是特殊方案。
URL如果其主机为null或为空字符串,或者其方案是"file"
,则不能具有用户名/密码/端口。
URL可以被指定为基础URL。
基础URL对于URL解析器很有用,当输入可能是相对URL字符串时。
Windows 驱动器号 是两个码点,第一个是 ASCII 字母,第二个是 U+003A (:) 或 U+007C (|)。
规范化的 Windows 驱动器号 是 Windows 驱动器号,其中第二个码点是 U+003A (:)。
根据 URL 写入 部分,只有 规范化的 Windows 驱动器号 是合规的。
如果符合以下所有条件,则字符串 以 Windows 驱动器号开头:
- 它的长度大于或等于2
- 它的前两个码点是Windows 驱动器号
- 它的长度为2,或其第三个码点是 U+002F (/)、U+005C (\)、U+003F (?) 或 U+0023 (#)。
要缩短 url 的路径:
4.3. URL 写入
有效 URL 字符串必须是带片段的相对 URL 字符串或带片段的绝对 URL 字符串。
带片段的绝对 URL 字符串必须是 一个绝对 URL 字符串,可选地后跟 U+0023 (#) 和一个URL 片段字符串。
绝对 URL 字符串必须是以下之一:
-
一个URL-方案 字符串,其与某个ASCII 大小写不敏感匹配的 特殊方案相匹配, 且不与 "
file" ASCII 大小写不敏感匹配, 后跟 U+003A (:) 和一个方案相对特殊 URL 字符串 -
一个URL-方案 字符串,其不与任何ASCII 大小写不敏感匹配的 特殊方案相匹配, 后跟 U+003A (:) 和以下之一:一个方案相对 URL 字符串、一个 路径绝对非授权 URL 字符串, 或一个不透明路径 URL 字符串
-
一个URL-方案 字符串,其与 "
file" ASCII 大小写不敏感匹配,后跟 U+003A (:) 和一个方案相对 file URL 字符串
以上任一项都可选择后跟 U+003F (?) 和一个URL-查询字符串。
一个URL-方案字符串必须是一个ASCII 字母, 后跟零个或多个ASCII 字母数字、U+002B (+)、U+002D (-) 和 U+002E (.)。 方案应被 注册在 IANA URI [sic] Schemes 注册表中。 [IANA-URI-SCHEMES] [RFC7595]
一个带片段的相对 URL 字符串 必须是 U+0023 (#) 后跟一个URL-片段字符串,如果基 URL具有 不透明路径;否则,为一个 相对 URL 字符串,可选择后跟 U+0023 (#) 和一个URL-片段 字符串。
一个相对 URL 字符串必须是:
-
- 一个不是 "
file" 的特殊方案 - "
file" - 否则
- 一个不是 "
以上任一项都可选择后跟 U+003F (?) 和一个URL-查询字符串。
在解析 带片段的相对 URL 字符串时,需要一个非 null 的基 URL。
一个方案相对特殊 URL
字符串必须是
"//",后跟一个
有效主机字符串,
可选择后跟 U+003A (:) 和一个URL-端口字符串,可选择
后跟一个路径绝对 URL
字符串。
一个URL-端口字符串必须是以下之一:
一个方案相对 URL 字符串必须是
"//",后跟一个不透明主机和端口字符串,可选择后跟一个
路径绝对 URL
字符串。
一个不透明主机和端口字符串必须为空字符串,或者是:一个 有效 不透明主机字符串,可选择后跟 U+003A (:) 和一个URL-端口字符串。
一个方案相对 file URL 字符串
必须
是 "//",可选择后跟以下之一:
-
一个有效主机 字符串,可选择后跟一个路径绝对 URL 字符串
-
一个路径绝对 URL 字符串。
一个路径绝对 URL 字符串必须是 U+002F (/), 后跟零个或多个URL-路径段字符串,彼此之间以 U+002F (/) 分隔。
一个路径绝对非授权 URL 字符串必须是一个路径绝对 URL 字符串, 且不以两个 U+002F (/) 码位开始。
一个路径相对 URL 字符串必须是零个 或多个 URL-路径段字符串,彼此之间以 U+002F (/) 分隔,且不以 U+002F (/) 开始。
一个 无方案路径相对 URL 字符串 必须是一个路径相对 URL 字符串,且不以下列内容开始:一个URL-方案字符串, 后跟 U+003A (:)。
一个不透明路径 URL 字符串必须是零个或多个URL 单元,不包括 U+003F (?),其中第一个(如果有)不是 U+002F (/)。
一个URL-路径段字符串必须是 以下之一:
-
零个或多个URL 单元, 不包括 U+002F (/) 和 U+003F (?),其整体不是一个 单点 URL 路径段或一个双点 URL 路径段。
-
一个双点 URL 路径段。
一个URL-查询字符串必须是零个或多个URL 单元。
一个URL-片段字符串必须是零个或多个 URL 单元。
URL 码点是 ASCII 字母数字、 U+0021 (!)、 U+0024 ($)、 U+0026 (&)、 U+0027 (')、 U+0028 左括号、 U+0029 右括号、 U+002A (*)、 U+002B (+)、 U+002C (,)、 U+002D (-)、 U+002E (.)、 U+002F (/)、 U+003A (:)、 U+003B (;)、 U+003D (=)、 U+003F (?)、 U+0040 (@)、 U+005F (_)、 U+007E (~), 以及范围 U+00A0 到 U+10FFFD(含)内的码 点,但不包括代理项和 非字符。
大于 U+007F DELETE 的码点将由URL 解析器转换为 百分号编码 字节。
在 HTML 中,当文档编码是遗留编码时, URL 查询字符串中 高于 U+007F DELETE 的码点将会 使用文档的编码转换为 百分号编码 字节。这 可能导致一个 URL 在一个文档中可用,但复制到另一个使用 不同文档编码的文档中时出现问题。处处使用 UTF-8 编码可以解决 这个问题。
例如,考虑此 HTML 文档:
<!doctype html>
< meta charset = "windows-1252" >
< a href = "?smörgåsbord" > Test</ a >
由于文档编码是 windows-1252,该链接的URL的查询
将是 "sm%F6rg%E5sbord"。如果文档编码曾是 UTF-8,则它会改为
"sm%C3%B6rg%C3%A5sbord"。
百分号编码字节可用于编码不是 URL 码点或被排除而不能写入的 码点。
无法在一个有效 URL 字符串中表达 一个用户名或密码,它们属于 URL 记录。
4.4. URL 解析
URL 解析器 接受一个 标量值字符串 input,带有一个可选的 null 或基 URL base(默认为 null)以及一个可选的编码 encoding(默认为 UTF-8), 然后运行以下步骤:
非 Web 浏览器实现只需要实现基本 URL 解析器。
Web 浏览器地址栏中的用户输入如何转换为 URL 记录,不在 本标准范围内。本标准确实包括 URL 渲染要求,因为它们与信任决策相关。
-
令 url 为在 input 上运行基本 URL 解析器 并带上 base 和 encoding 的结果。
-
如果 url 是 failure,返回 failure。
-
如果 url 的方案不是 "
blob",返回 url。 -
将 url 的blob URL 条目设为 解析 blob URL url 的结果,如果其没有返回 failure;否则设为 null。
-
返回 url。
基本 URL 解析器接受一个 标量值字符串 input,带有一个可选的 null 或基 URL base(默认为 null),一个可选的编码 encoding(默认为 UTF-8), 一个可选的URL url, 以及一个可选的状态覆盖 state override, 然后运行以下步骤:
encoding 参数是一个仅与 HTML 相关的遗留概念。 url 和 state override 参数仅供各种 API 使用。[HTML]
当没有传入 url 和 state override 参数时, 基本 URL 解析器返回一个新的URL或 failure。如果传入了它们, 该算法会修改传入的 url,并且可以在不返回任何内容的情况下终止。
-
如果没有给定 url:
-
将 url 设为一个新的URL。
-
如果 input 包含任何前导或尾随的C0 控制符或空格, invalid-URL-unit 验证错误。
-
从 input 中移除任何前导和尾随的C0 控制符或空格。
-
-
如果 input 包含任何ASCII 制表符或换行符,invalid-URL-unit 验证 错误。
-
从 input 中移除所有ASCII 制表符或换行符。
-
令 state 为 state override, 如果给定;否则为方案开始状态。
-
将 encoding 设为从 encoding 获取输出编码的结果。
-
令 buffer 为空字符串。
-
令 atSignSeen、insideBrackets 和 passwordTokenSeen 为 false。
-
令 pointer 为 input 的一个指针。
-
通过对 state 进行分支来持续运行以下状态机。如果一次运行之后 pointer 指向EOF 码位,转到下一步。否则,将 pointer 增加 1,并继续状态机。
- 方案开始状态
- 方案状态
-
-
如果 c 是一个ASCII 字母数字、U+002B (+)、U+002D (-) 或 U+002E (.), 将c 的小写化形式附加到 buffer。
-
否则,如果 c 是 U+003A (:),则:
-
如果给定了 state override,则:
-
将 url 的方案设为 buffer。
-
如果给定了 state override,则:
-
将 buffer 设为空字符串。
-
如果 url 的方案是 "
file", 则:-
如果剩余部分不是以 "
//" 开头, special-scheme-missing-following-solidus 验证错误。 -
将 state 设为file 状态。
-
-
否则,如果 url 是特殊的、base 为 非 null,且 base 的方案与 url 的方案相同:
-
将 state 设为特殊 相对或授权状态。
-
否则,如果剩余部分以一个 U+002F (/) 开头,将 state 设为 路径或授权状态,并 将 pointer 增加 1。
-
-
否则,如果没有给定 state override,将 buffer 设为空字符串,将 state 设为 无 方案状态,并重新开始(从 input 中的第一个码位 开始)。
-
否则,返回 failure。
此 failure 指示专门由
Location对象的protocolsetter 使用。此外,此状态中较早出现的非 failure 终止, 是为了定义该 setter 而有意设置的差异。
-
- 无方案状态
- 特殊相对或授权状态
-
-
如果 c 是 U+002F (/) 且剩余部分 以 U+002F (/) 开头,则将 state 设为特殊授权忽略 斜杠状态,并将 pointer 增加 1。
-
否则,产生special-scheme-missing-following-solidus 验证错误,将 state 设为相对状态,并将 pointer 减少 1。
-
- 路径或授权状态
- 相对状态
- 相对斜杠状态
- 特殊授权斜杠状态
-
-
如果 c 是 U+002F (/) 且剩余部分 以 U+002F (/) 开头,则将 state 设为特殊授权 忽略斜杠状态,并将 pointer 增加 1。
-
否则,产生special-scheme-missing-following-solidus 验证错误,将 state 设为特殊授权 忽略斜杠状态,并将 pointer 减少 1。
-
- 特殊权限忽略斜杠状态
- 权限状态
-
-
如果 c 是 U+0040 (@),则:
-
如果 atSignSeen 为 true,则将 "
%40" 前置到 buffer。 -
将 atSignSeen 设为 true。
-
对 buffer 中的每个 codePoint:
-
如果 codePoint 是 U+003A (:) 且 passwordTokenSeen 为 false, 则将 passwordTokenSeen 设为 true,并继续。
-
令 encodedCodePoints 为使用 userinfo 百分比编码集对 codePoint 运行 UTF-8 百分比编码 的结果。
-
如果 passwordTokenSeen 为 true,则将 encodedCodePoints 追加到 url 的password。
-
否则,将 encodedCodePoints 追加到 url 的 username。
-
-
将 buffer 设为空字符串。
-
否则,如果以下之一为 true:
则:
-
如果 atSignSeen 为 true 且 buffer 是空 字符串, host-missing 验证 错误,返回失败。
-
将 pointer 减少 buffer 的 码点长度 + 1, 将 buffer 设为空字符串,并将 state 设为 主机状态。
-
-
否则,将 c 追加到 buffer。
-
- 主机状态
- 主机名状态
- 端口状态
-
-
否则,如果以下之一为 true:
则:
-
如果 buffer 不是空字符串:
-
令 port 为 buffer 以 radix-10 表示的数学整数值, 对值为 0 到 9 的数字使用 ASCII 数字。
-
如果 port 不是一个 16 位无符号 整数, port-out-of-range 验证错误,返回 失败。
-
将 buffer 设为空字符串。
-
如果给定了 state override,则返回。
-
-
如果给定了 state override,则返回失败。
-
将 state 设为 路径开始状态,并将 pointer 减少 1。
-
-
否则,port-invalid 验证 错误,返回失败。
- 文件状态
-
-
将 url 的scheme 设为 "
file"。 -
将 url 的host 设为空字符串。
-
如果 c 是 U+002F (/) 或 U+005C (\),则:
-
如果 c 是 U+005C (\),invalid-reverse-solidus 验证错误。
-
将 state 设为 文件斜杠状态。
-
-
否则,如果 base 非 null,且 base 的scheme 是 "
file":-
将 url 的host 设为 base 的host, 将 url 的path 设为 base 的 path 的一个克隆,并将 url 的query 设为 base 的 query。
-
否则,如果 c 是 U+0023 (#),则将 url 的fragment 设为 空字符串,并将 state 设为 片段 状态。
-
-
否则,将 state 设为 路径状态,并将 pointer 减少 1。
-
- 文件斜杠状态
-
-
如果 c 是 U+002F (/) 或 U+005C (\),则:
-
如果 c 是 U+005C (\),invalid-reverse-solidus 验证错误。
-
将 state 设为 文件主机状态。
-
-
否则:
-
- 文件主机状态
-
-
如果 c 是 EOF 码点、U+002F (/)、U+005C (\)、 U+003F (?) 或 U+0023 (#),则将 pointer 减少 1,然后:
-
如果未给定 state override,且 buffer 是一个 Windows 驱动器盘符,file-invalid-Windows-drive-letter-host 验证错误,将 state 设为 路径状态。
这是一个(与平台无关的)Windows 驱动器 盘符怪癖。buffer 在这里不重置,而是在路径状态中使用。
-
否则,如果 buffer 是空字符串,则:
-
否则,运行这些步骤:
-
-
否则,将 c 追加到 buffer。
-
- 路径开始状态
-
-
如果 url 是特殊的,则:
-
如果 c 是 U+005C (\),invalid-reverse-solidus 验证错误。
-
将 state 设为 路径状态。
-
如果 c 既不是 U+002F (/) 也不是 U+005C (\),则将 pointer 减少 1。
-
-
否则,如果未给定 state override 且 c 是 U+003F (?),则将 url 的query 设为空字符串,并将 state 设为 查询 状态。
-
否则,如果未给定 state override 且 c 是 U+0023 (#),则将 url 的fragment 设为空字符串,并将 state 设为 片段状态。
-
否则,如果给定了 state override,且 url 的 host 为 null,则将空字符串追加到 url 的 path。
-
- 路径状态
-
-
如果以下之一为 true:
则:
-
如果 url 是特殊的,且 c 是 U+005C (\), invalid-reverse-solidus 验证错误。
-
如果 buffer 是一个双点 URL 路径 片段,则:
-
否则,如果 buffer 是一个单点 URL 路径 片段,并且 c 不是 U+002F (/), 且也不是 url 是特殊的并且 c 是 U+005C (\),则将空字符串 追加到 url 的path。
-
否则,如果 buffer 不是一个单点 URL 路径 片段,则:
-
将 buffer 设为空字符串。
-
如果 c 是 U+0023 (#),则将 url 的fragment 设为 空字符串,并将 state 设为 片段 状态。
-
-
否则,运行这些步骤:
-
如果 c 不是一个URL 码点,也不是 U+0025 (%), invalid-URL-unit 验证错误。
-
如果 c 是 U+0025 (%) 且 remaining 不是以两个 ASCII 十六进制数字开头,invalid-URL-unit 验证错误。
-
使用 路径百分比编码集对 c 进行 UTF-8 百分比编码, 并将结果追加到 buffer。
-
-
- 不透明路径状态
-
-
否则,如果 c 是 U+0023 (#),则将 url 的fragment 设为空字符串,并将 state 设为 片段状态。
-
否则,如果 c 是 U+0020 SPACE:
-
-
如果 c 不是一个URL 码点,也不是 U+0025 (%), invalid-URL-unit 验证错误。
-
如果 c 是 U+0025 (%) 且 remaining 不是以两个 ASCII 十六进制数字开头,invalid-URL-unit 验证错误。
-
使用 C0 控制 百分比编码集对 c 进行 UTF-8 百分比编码, 并将结果追加到 url 的 path。
-
- 查询状态
-
-
如果 encoding 不是 UTF-8 且以下之一为 true:
则将 encoding 设为 UTF-8。
-
如果以下之一为 true:
则:
-
如果 url 是特殊的,则令 queryPercentEncodeSet 为 special-query 百分比编码集;否则为查询百分比编码集。
-
使用 encoding、 buffer 和 queryPercentEncodeSet,执行 编码后百分比编码, 并将结果追加到 url 的query。
由于有状态的 ISO-2022-JP 编码器,此操作不能 逐码点调用。
-
将 buffer 设为空字符串。
-
如果 c 是 U+0023 (#),则将 url 的fragment 设为 空字符串,并将 state 设为 片段 状态。
-
-
-
如果 c 不是一个URL 码点,也不是 U+0025 (%), invalid-URL-unit 验证错误。
-
如果 c 是 U+0025 (%) 且 remaining 不是以两个 ASCII 十六进制数字开头,invalid-URL-unit 验证错误。
-
将 c 追加到 buffer。
-
-
- 片段状态
-
-
-
如果 c 不是一个URL 码点,也不是 U+0025 (%), invalid-URL-unit 验证错误。
-
如果 c 是 U+0025 (%) 且 remaining 不是以两个 ASCII 十六进制数字开头,invalid-URL-unit 验证错误。
-
使用 片段百分比编码 集对 c 进行 UTF-8 百分比编码, 并将结果追加到 url 的 fragment。
-
-
-
返回 url。
要给定 url 和 username 设置用户名,将 url 的 用户名 设置为运行 UTF-8 百分比编码 在 username 上,并使用 用户信息百分比编码集 的结果。
要给定 url 和 password 设置密码,将 url 的 密码 设置为运行 UTF-8 百分比编码 在 password 上,并使用 用户信息百分比编码集 的结果。
4.5. URL 序列化
URL 序列化器接受一个 URL url,带有一个 可选布尔值 exclude fragment(默认为 false),然后 运行 以下步骤。它们返回一个ASCII 字符串。
-
令 output 为 url 的方案与 U+003A (:) 拼接的结果。
-
如果 url 的主机为非 null:
-
如果 url 的主机为 null,url 不具有 不透明路径, url 的路径的大小大于 1,且 url 的路径[0] 是空字符串,则将 U+002F (/) 后跟 U+002E (.) 附加到 output。
这会防止
web+demo:/.//not-a-host/或web+demo:/path/..//not-a-host/在被解析然后 序列化后,最终变成web+demo://not-a-host/(它们 最终会成为web+demo:/.//not-a-host/)。 -
将对 url 进行URL 路径序列化的结果附加到 output。
-
如果 exclude fragment 为 false,且 url 的片段为 非 null,则将 U+0023 (#) 后跟 url 的片段附加到 output。
-
返回 output。
4.6. URL 等价性
4.7. 源
请参阅 源在 HTML 中的定义,获取必要的背景信息。[HTML]
URL 的源是通过以下步骤,根据 url 的 方案 切换得出的:
- "
blob" -
-
如果 url 的 blob URL 项 非空,则返回 url 的 blob URL 项 的 环境 的 源。
-
如果 pathURL 失败,则返回一个新的不透明源。
-
返回一个新的不透明源。
blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f的源是元组源 ("https"、"whatwg.org"、null、null)。 -
- "
ftp"- "
http"- "
https"- "
ws"- "
wss" - "
- "
file" -
尽管令人遗憾,这个问题留给读者自行解决。当不确定时,返回一个新的不透明源。
- 其他
-
返回一个新的不透明源。
4.8. URL 渲染
当显示 URL 的主要目的是让用户做出安全或信任决定时,应该以其 序列化形式进行渲染,并进行如下所述的修改。例如,用户应根据浏览器地址栏中渲染的 URL 来做出信任决定。
4.8.1. 简化非人类可读或无关的组件
删除可能提供欺骗机会或分散安全相关信息的组件:
-
在用户区分 URL 的主机和其他部分(如 路径)时,浏览器可以只显示 URL 的 主机。浏览器还可以进一步简化主机,突出其 可注册域。例如,浏览器可以省略前导的
www或m域标签,或只显示其可注册域,以消除子域名引发的欺骗机会(例如,https://examplecorp.attacker.com/)。 -
浏览器不应渲染 URL 的 用户名和密码,因为它们可能会被误认为是 URL 的 主机(例如,
https://[email protected]/)。 -
如果显示界面仅允许使用单一方案,浏览器可以不渲染 URL 的 方案(例如浏览器功能省略了
https://,因为它仅对安全来源启用)。否则,方案可以被替换或补充为人类可读的字符串(例如“非安全”),安全指示符图标,或两者兼具。
4.8.2. 省略
在空间受限的显示中,URL 应小心省略,以避免误导用户做出安全决定:
-
浏览器应确保在 URL 被渲染时,至少能够显示可注册域 (以避免在加载
https://not-really-examplecorp.com/时,显示例如...examplecorp.com)。 -
当完整的主机无法被渲染时,浏览器应从最低级域标签开始省略 域标签。例如,
examplecorp.com.evil.com应被省略为...com.evil.com,而不是examplecorp.com...。(注意,双向文本意味着最低级域 标签可能不会出现在左侧。)
4.8.3. 国际化和特殊字符
国际化域名(IDN)、特殊字符和双向文本应谨慎处理,以防止欺骗:
-
如果 URL 的主机是一个域,浏览器 应通过使用该 URL 的主机运行域转 Unicode来渲染它。
各种字符都可被用于同形异义欺骗攻击。请考虑 检测 易混淆字符,并在它们被使用时发出警告。[IDNFAQ] [UTS39]
-
当 URL 包含双向文本时,特别容易在主机和路径之间产生混淆, 因此在这种情况下,尤其建议只渲染 URL 的 主机。为提高 可读性,如果渲染 URL 的其他部分,应将其中的 百分号编码字节序列替换为码位,这些码位由对这些序列的 百分号解码运行 不带 BOM 的 UTF-8 解码而得到, 除非这会使这些序列渲染为不可见。浏览器可以选择不解码某些 会带来欺骗风险的序列(例如 U+1F512 (🔒))。
-
浏览器应像处于从左到右嵌入中一样渲染双向文本。[BIDI]
遗憾的是,由于被渲染的 URL是字符串并且可以出现在任何地方,针对被渲染 URL的特定双向算法不会被广泛采用。 双向文本会以可能导致渲染不同于模型的方式,与 URL 的各部分相互作用。双向语言的用户可能会预期到 这一点,尤其是在纯文本环境中。
5.
application/x-www-form-urlencoded
application/x-www-form-urlencoded 格式提供了一种对 列表 中的 元组(每个元组包含一个名称和一个值)进行编码的方法。
application/x-www-form-urlencoded
格式在许多方面是一种异常的怪物,它是多年实现事故和妥协的结果,导致了一组为了互操作性而必需的要求,但绝不代表良好的设计实践。尤其是,读者应特别注意涉及字符编码和字节序列之间的多次(有时是嵌套的)转换的复杂细节。不幸的是,由于
HTML 表单的广泛使用,这种格式被广泛使用。[HTML]
5.1. application/x-www-form-urlencoded 解析
旧的面向服务器的实现可能必须支持 编码,如 UTF-8
以外的编码,以及对名称为 _charset 的元组进行特殊处理。此处未描述此类逻辑,因为仅 UTF-8 是合规的。
application/x-www-form-urlencoded 解析器 接受一个字节序列
input,然后运行以下步骤:
-
将 sequences 设为通过 0x26 (&) 拆分 input 的结果。
-
将 output 设为一个最初为空的名称-值元组的 列表,其中名称和值都存储为字符串。
-
对每个 字节序列 bytes 在 sequences 中:
-
如果 bytes 是空字节序列,则 继续。
-
如果 bytes 包含 0x3D (=),则将 name 设为从 bytes 开头到其第一个 0x3D (=)(不包括)的字节,value 设为(如果有)从第一个 0x3D (=) 之后到 bytes 结尾的字节。如果 0x3D (=) 是第一个字节,则 name 将为空字节序列。如果是最后一个字节,则 value 将为空字节序列。
-
否则,将 name 设为 bytes 的值,并将 value 设为空字节序列。
-
将 name 和 value 中的任何 0x2B (+) 替换为 0x20 (SP)。
-
将 nameString 和 valueString 设为分别对 name 和 value 进行无 BOM 的 UTF-8 解码并 百分比解码 的结果。
-
将 (nameString, valueString) 附加到 output。
-
-
返回 output。
5.2. application/x-www-form-urlencoded 序列化
application/x-www-form-urlencoded 序列化器
接受一个名称-值元组的列表 tuples,可选地带有一个编码
encoding(默认 UTF-8),然后运行以下步骤。它们返回一个ASCII 字符串。
-
将 encoding 设置为通过 获取输出编码 获得的结果。
-
将 output 设为空字符串。
-
对每个 tuple 在 tuples 中:
-
令 name 为以 编码后百分号编码 配合 encoding、tuple 的 name 和
application/x-www-form-urlencoded百分号编码集 运行的结果。 -
令 value 为以 编码后百分号编码 配合 encoding、tuple 的 value 和
application/x-www-form-urlencoded百分号编码集 运行的结果。 -
如果 output 不是空字符串,则追加 U+0026 (&) 到 output。
- 将 name、U+003D (=) 和 value 依次追加到 output。
- 返回 output。
5.3. 挂钩
application/x-www-form-urlencoded 字符串解析器 接受一个标量值字符串 input,UTF-8 编码 它,然后返回 application/x-www-form-urlencoded 解析 它的结果。
6. API
本节使用了 Web IDL 中的术语。浏览器用户代理必须支持此 API。JavaScript 实现应支持此 API。其他用户代理或编程语言则被鼓励使用适合其需求的 API,可能不是此 API。[WEBIDL]
6.1. URL 类
[Exposed=*,LegacyWindowAlias =]webkitURL interface {URL constructor (USVString ,url optional USVString );base static URL ?parse (USVString ,url optional USVString );base static boolean canParse (USVString ,url optional USVString );base stringifier attribute USVString href ;readonly attribute USVString origin ;attribute USVString protocol ;attribute USVString username ;attribute USVString password ;attribute USVString host ;attribute USVString hostname ;attribute USVString port ;attribute USVString pathname ;attribute USVString search ; [SameObject ]readonly attribute URLSearchParams searchParams ;attribute USVString hash ;USVString toJSON (); };
A URL 对象有一个关联的:
- URL:一个 URL。
- 查询对象:一个
URLSearchParams对象。
API URL 解析器 接受一个 标量值字符串 url 和一个可选的 null 或 标量值字符串 base(默认为 null),然后运行以下步骤:
-
让 parsedBase 为 null。
-
如果 base 不为 null:
-
将 parsedBase 设置为运行 基本 URL 解析器 在 base 上的结果。
-
如果 parsedBase 失败,则返回失败。
-
-
返回运行 基本 URL 解析器 在 url 和 parsedBase 上的结果。
new URL(url, base) 构造函数的步骤如下:
-
将 parsedURL 设置为运行 API URL 解析器 在 url 和 base 上的结果,如果有提供 base。
要在不使用
基础 URL的情况下,将字符串解析为一个URL,请使用单个参数调用
URL 构造函数:
var input = "https://example.org/💩" ,
url = new URL( input)
url. pathname // "/%F0%9F%92%A9"
如果输入是相对 URL 字符串,则会抛出异常:
try {
var url = new URL( "/🍣🍺" )
} catch ( e) {
// that happened
}
对于这些情况,必须有一个基础 URL:
var input = "/🍣🍺" ,
url = new URL( input, document. baseURI)
url. href // "https://url.spec.whatwg.org/%F0%9F%8D%A3%F0%9F%8D%BA"
URL 对象可以被
用作基础 URL
(由于 IDL 要求参数是字符串,
URL 对象
会字符串化为其 href
getter 的返回值):
var url = new URL( "🏳️🌈" , new URL( "https://pride.example/hello-world" ))
url. pathname // "/%F0%9F%8F%B3%EF%B8%8F%E2%80%8D%F0%9F%8C%88"
静态方法 parse(url, base) 的步骤如下:
-
将 parsedURL 设置为运行 API URL 解析器 在 url 和 base 上的结果,如果有提供 base。
-
如果 parsedURL 失败,则返回 null。
-
让 url 成为一个新的
URL对象。 -
初始化 url,使用 parsedURL。
-
返回 url。
静态 canParse(url, base)
方法步骤如下:
-
令 parsedURL 为对 url 以及给定的 base 执行 API URL 解析器 的结果。
-
如果 parsedURL 失败,则返回 false。
-
返回 true。
href
setter 步骤如下:
-
令 parsedURL 为对给定值运行 基本 URL 解析器 的结果。
-
清空 此对象的 query object 的 list。
-
如果 query 不为 null,则将 此对象的 query object 的 list 设为 解析 query 的结果。
protocol
setter 步骤为
基本 URL
解析 给定值和 U+003A (:),
以 此对象 的 URL 作为 url,
以 scheme start
state 作为
state override。
host getter 步骤为:
host
setter 步骤为:
如果给
host
setter 的给定值缺少
端口,this 的URL的端口不会
改变。这可能出乎意料,因为 host getter 确实会返回一个URL-端口字符串,所以
人们可能会以为 setter 总是会“重置”二者。
hostname
setter 步骤是:
port
setter 步骤是:
pathname getter 步骤是返回对
this 的URL进行URL 路径
序列化的结果。
pathname
setter 步骤是:
search
setter 步骤是:
hash
setter 步骤是:
6.2. URLSearchParams 类
[Exposed=*]interface {URLSearchParams constructor (optional (sequence <sequence <USVString >>or record <USVString ,USVString >or USVString )= "");init readonly attribute unsigned long size ;undefined append (USVString ,name USVString );value undefined delete (USVString ,name optional USVString );value USVString ?get (USVString );name sequence <USVString >getAll (USVString );name boolean has (USVString ,name optional USVString );value undefined set (USVString ,name USVString );value undefined sort ();iterable <USVString ,USVString >;stringifier ; };
构造并序列化一个 URLSearchParams
对象非常简单:
let params = new URLSearchParams({ key: "730d67" })
params. toString() // "key=730d67"
由于 URLSearchParams
对象底层使用 application/x-www-form-urlencoded
格式,因此它对某些代码点的编码方式与 URL 对象(包括
href
和 search)相比存在一些差异。当使用
searchParams
操作 URL 的查询时,这一点尤其令人惊讶。
const url = new URL( 'https://example.com/?a=b ~' );
console. log( url. href); // "https://example.com/?a=b%20~"
url. searchParams. sort();
console. log( url. href); // "https://example.com/?a=b+%7E"
const url = new URL( 'https://example.com/?a=~&b=%7E' );
console. log( url. search); // "?a=~&b=%7E"
console. log( url. searchParams. get( 'a' )); // "~"
console. log( url. searchParams. get( 'b' )); // "~"
URLSearchParams
对象会对 application/x-www-form-urlencoded
percent-encode set 中的任何字符进行百分比编码,并将 U+0020 SPACE 编码为 U+002B (+)。
忽略编码(使用 UTF-8),search
将对查询百分比编码集或特殊查询百分比编码集中的任何内容进行百分比编码(取决于URL 是否特殊)。
一个 URLSearchParams
对象具有一个关联的:
要初始化一个 URLSearchParams
对象 query(使用 init):
要更新一个 URLSearchParams
对象 query:
new URLSearchParams(init)
构造函数的步骤是:
delete(name, value) 方法的步骤是:
has(name, value)
方法的步骤如下:
set(name, value)
方法的步骤如下:
对 URLSearchParams
对象中的 name-value 元组进行排序在某些情况下是有用的,尤其可以提高缓存命中率。可以通过调用
sort()
方法实现:
const url = new URL( "https://example.org/?q=🏳️🌈&key=e1f7bc78" );
url. searchParams. sort();
url. search; // "?key=e1f7bc78&q=%F0%9F%8F%B3%EF%B8%8F%E2%80%8D%F0%9F%8C%88"
为了避免修改原始输入,比如用于比较,可以新建一个
URLSearchParams
对象:
const sorted = new URLSearchParams( url. search)
sorted. sort()
可迭代的键值对为 此对象的 列表中的 元组,键为名称,值为 value。
6.3. 其他标准中的 URL API
暴露 URL 的标准,应当以字符串形式暴露 URL(通过对内部 URL 进行 序列化)。标准不应当使用 URL 对象来暴露 URL。URL 对象仅用于 URL 操作。在 IDL 中应使用 USVString 类型。
这里的高层次概念是值应当作为不可变的数据结构公开。
如果某标准决定使用 "URL" 名称的变体来定义其功能,建议将此功能命名为 "url"(即小写,并且以 "l" 结尾)。不应使用 "URL"、"URI" 和 "IRI" 等名称。然而,如果名称是复合词,建议使用 "URL"(即大写),例如 "newURL" 和 "oldURL"。
接口 EventSource
和 HashChangeEvent
是 HTML 中正确命名的示例。 [HTML]
致谢
多年来,许多人帮助使 URL 变得更加互操作,从而推动了本标准的目标。同样,许多人帮助将本标准发展成今天的样子。
在此,特别感谢以下人士: 100の人, Adam Barth, Addison Phillips, Adrián Chaves, Adrien Ricciardi, Albert Wiersch, Alex Christensen, Alexandre Morgaut, Alexis Hunt, Alwin Blok, Andrew Sullivan, Arkadiusz Michalski, Behnam Esfahbod, Bobby Holley, Boris Zbarsky, Brad Hill, Brandon Ross, Cailyn Hansen, Chris Dumez, Chris Rebert, Corey Farwell, Dan Appelquist, Daniel Bratell, Daniel Stenberg, David Burns, David Håsäther, David Sheets, David Singer, David Walp, Domenic Denicola, Emily Schechter, Emily Stark, Eric Lawrence, Erik Arvidsson, Gavin Carothers, Geoff Richards, Glenn Maynard, Gordon P. Hemsley, hemanth, Henri Sivonen, Ian Hickson, Ilya Grigorik, Italo A. Casas, Jakub Gieryluk, James C. Wise, James Graham, James Manger, James Ross, Jeff Hodges, Jeffrey Posnick, Jeffrey Yasskin, Joe Duarte, Joshua Bell, Jxck, Karl Wagner, Kemal Zebari, 田村健人 (Kent TAMURA), Kevin Grandon, Kornel Lesiński, Larry Masinter, Leif Halvard Silli, Mark Amery, Mark Davis, Marcos Cáceres, Marijn Kruisselbrink, Martin Dürst, Mathias Bynens, Matt Falkenhagen, Matt Giuca, Michael Peick, Michael™ Smith, Michal Bukovský, Michel Suignard, Mikaël Geljić, Nikita Skovoroda, Noah Levitt, Peter Occil, Philip Jägenstedt, Philippe Ombredanne, Prayag Verma, Rimas Misevičius, Robert Kieffer, Rodney Rehm, Roy Fielding, Ryan Sleevi, Sam Ruby, Sam Sneddon, Santiago M. Mola, Sebastian Mayr, Shannon Booth, Simon Pieters, Simon Sapin, Steven Vachon, Stuart Cook, Sven Uhlig, Tab Atkins, 吉野剛史 (Takeshi Yoshino), Tantek Çelik, Tiancheng "Timothy" Gu, Tim Berners-Lee, 簡冠庭 (Tim Guan-tin Chien), Titi_Alone, Tomek Wytrębowicz, Trevor Rowbotham, Tristan Seligmann, Valentin Gosu, Vyacheslav Matva, Wei Wang, Wolf Lammen, 山岸和利 (Yamagishi Kazutoshi), Yongsheng Zhang, 成瀬ゆい (Yui Naruse),以及 zealousidealroll, 你们真棒!
本标准由 Anne van Kesteren 编写(Apple,[email protected])。
知识产权
版权 © WHATWG (Apple, Google, Mozilla, Microsoft)。此作品依据 知识共享署名 4.0 国际许可协议 授权。若本作品的部分内容被纳入源代码,则源代码部分依据 BSD 3-Clause 许可协议 授权。
这是现行标准。对专利审核版感兴趣的用户可以查看 现行标准审核草案。