AT-URI 语法混乱

Lobsters Hottest 新闻

摘要

本文讨论了 AT URI 语法因将 DID 放在 authority 字段而导致与标准 URI/URL 规范不兼容的问题,并探讨了潜在的解决方案及其权衡。

<p><a href="https://lobste.rs/s/7fjqgc/at_uri_syntax_mess">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/06/29 22:33

# AT-URI 语法乱局 - at:// pizza thoughts 来源:https://bnewbold.leaflet.pub/3mph4hzvbdc2v home oven baking a pizza home oven baking a pizza 是时候处理 atproto 规范中最令人遗憾的缺陷之一了:AT URI 语法,按照当前规范,并不是一个有效的 URI 或 URL。我们把 DID 放在 URI 的 "authority" 位置(紧接在 `at://` 之后),这与 RFC 3986(https://www.rfc-editor.org/info/rfc3986/#section-3.2)中规定的 host/port 层次化 URI 语法组件存在冲突。核心问题在 2025 年就被提出(由 @mcc 在 [这个 GitHub issue](https://github.com/bluesky-social/atproto-website/issues/417) 中提出),现在之所以迫在眉睫,有两个原因。首先,越来越多的人试图在期望格式良好的 URI(或 URL)的地方使用 AT URI,例如在 HTML `<a>` 标签中。其次,IETF 的 ATP 工作组(https://datatracker.ietf.org/doc/charter-ietf-atp/)有一项交付物,即标准化 AT URI 方案并进行永久注册。本文的目的是提供一些背景情况,然后讨论一些可能的修复方法。不幸的是,我认为目前并没有完美的方案:无论生态系统选择哪条路,都不可避免地会带来一些开发者的痛苦和中断。我非常关注这个问题,因为我认为 AT URI 是协议中最好也最重要的功能之一!将个人账户标识符放在 authority 部分,而不是提供商主机名,既是 atproto 核心理念的具体体现,也具有象征意义:账户是其内容的最终权威,并且可以在不同托管提供商之间无缝迁移。账户掌握主导权,并能解析到当前的网络位置。这一方面不会改变,如果我们能解决这个语法乱局,那么大家就可以放开手脚,到处使用 AT URI 了。 ## 哪里出错了?(https://bnewbold.leaflet.pub/3mph4hzvbdc2v#what-went-wrong) 为了接地气一点,这里有一个指向特定记录的 AT URI 示例,authority 位置包含了一个 DID: ``` at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g ``` 以及通用语法: ``` at://<account>/<collection>/<recordKey> ``` `at:` URI 方案最初设计于 2022 年,并于 2023 年进行了临时注册(https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml)。我们当时知道将 DID 放入 authority 部分可能会导致兼容性问题,并且意味着该语法在 WHATWG 规范下不是有效的 Web URL。但我们(错误地)认为它仍然符合 RFC-3986 中标准化的 URI 语法。 设计 AT Protocol 一直是团队努力的结果,包括 Bluesky 内外,但我个人对这个特定的语法乱局感到有责任。我在 2023 年春天花了相当多时间审查和"强化"书面规范,以期精准地捕获此类问题。 问题的根源来自于对 RFC-3986 的动机性解读,特别是第 1.2.3 节(https://www.rfc-editor.org/info/rfc3986/#section-1.2.3): > 对于某些 URI 方案,可见的层次结构仅限于方案本身:方案组件分隔符(":")之后的所有内容都被视为 URI 处理中的不透明部分。 当时我将其解释为,基本原则是 URI 就是方案名称加冒号字符。之后的所有内容,如第 3.2、3.3 节等所述,似乎是可选的"层次化"语法,可以忽略。有许多有效的 URI 方案就是这样做的,比如电子邮件(`mailto:[email protected]`)、Usenet(`news:comp.infosystems.www.servers.unix`)。针对计划进行永久 IANA 注册的 URI 的进一步指导(我们希望 AT URI 方案具备这一点)在 RFC-7595 第 3.2 节(https://www.rfc-editor.org/info/rfc7595/#section-3.2)中有描述,其中指出: > 方案应避免不当使用 "//"。URI 第一部分中使用双斜杠并不是表示其后是 URI 的风格性指示:双斜杠仅当 <scheme-specific-part> 的语法包含层次化结构时才应使用。在此类方案的 URI 中,使用双斜杠表示其后是命名权限的顶级层次化元素(RFC 3986 第 3.2 节有更多细节)。不包含符合要求的层次化结构的方案在其 <scheme-specific-part> 中不应在 ":" 字符串后使用双斜杠。 这清楚地说明了最佳实践,尽管我要指出这些是"应"(SHOULD)而非"必须"(MUST)。总体来看,似乎很清楚,当使用 `//` 时,通用/层次化语法限制是必须要求的。RFC-3986 附录 A(https://www.rfc-editor.org/info/rfc3986/#appendix-A)中的正式 ABNF 语法要求了这一点。WHATWG URL 语法(https://url.spec.whatwg.org/)对此没有留下任何模糊空间。在实际层面上,实际的字符串无法被大多数现实世界中的 URL 和 URI 库解析。 为什么会首先有这样的动机性推理?因为我们喜欢当前简单的语法。它简洁且符合习惯。对开发者来说看起来很熟悉,不涉及任何编码/解码或字符串篡改,并且借鉴了现成的语义。因为 DID 总是至少有两个冒号,与主机名(或 IP 地址)混淆实际上并不模糊。如果 URI 语法是有效的,感觉随着时间的推移,有可能在其他地方获得支持,比如在浏览器和通用 URI 解析库中。 ## 我们能做些什么?(https://bnewbold.leaflet.pub/3mph4hzvbdc2v#what-can-we-do-about-it) 目前有数十亿个 AT URI 存在于外部。其中许多位于内容寻址的数据记录中,这些记录如果不改变记录版本(哈希)就无法更新。或者存在于来自数百个提供商的数百万个加密签名标签对象中。这意味着当前的语法将在未来很长一段时间内被遇到,并且至少需要 atproto 实现部分支持。 考虑到这一点,我认为生态系统可以采取几种广泛的方法: 1. **保留现有语法,并且不再称其为"URI"**:例如,将它们称为"AT 引用标识符"之类的名称。这将意味着放弃 IETF 工作组章程中标准化 URI 方案的目标。这也会在尝试在 Web 上、其他协议中等使用这些字符串时引起无休止的混淆和歧义。我认为这是一个糟糕的结果,我们不应该走这条路。 2. **保留现有语法,并争取改变 IETF URI 语法规则**:这将是一个巨大的工程,有点像"移山"行动。需要大量的标准机构外交和社会资本,可能需要数年时间。我确实认为结果可能对 atproto 生态系统和整体互联网协议空间都是最好的。我认为如果 authority 部分在通用情况下更灵活,URI/URL 规范会更简洁,实现也会更清晰。这将使未来的协议和 URI 方案更容易使用替代语义,而无需编码或字符串篡改技巧。但这是一个大赌注,我不确定尝试它是否明智。 3. **更改 AT URI 语法以符合 IETF 规范**:我们可以采取几种不同的方法,我在下面单独讨论。它们都不如当前语法简洁,并且 atproto 实现需要同时支持两个版本,并谨慎处理规范化和相等性检查。推出更改将花费很长时间,占用开发者的时间和注意力,并且在此过程中一定程度上的用户影响性断裂感觉不可避免(因为并非所有已部署的软件都会支持新语法)。另一方面,人们可以更早地开始与其他软件和协议进行集成,并且 IETF 工作组将更容易通过初始章程。 我目前的感受是,我们应该并行探索第二和第三种方案。弄清楚这些方案实际上需要多少工作和破坏,提出更具体的建议,并与人们讨论。做出最终决定的地点应该是 IETF 工作组(即在邮件列表上),尽管我们也应该考虑更广泛的 atproto 开发者生态系统的意见。 ## 替代语法(https://bnewbold.leaflet.pub/3mph4hzvbdc2v#alternative-syntax) 我们如何更改 AT URI 语法以使其在现有 IETF URI 规则下有效?就个人而言,我广泛反对涉及不同 URI 方案、字符串编码/解码、替代标识符或标识符篡改的方法。我将首先简要介绍几个这类示例。 一个更直接的方法是在 authority 部分对 DID 进行百分号编码。所以,不用 `at://did:plc:abc123/...`,而是使用 `at://did%3Aplc%3Aabc123/...`。这样做的一个好处是,将来可以使用含有保留字符的 DID 方法,甚至其他非 DID 标识符。但我们从它们在 Web URL 中的使用知道,百分号编码可能非常麻烦。它们看起来丑陋且不清晰,因此人们通常会以原始形式显示它们。将整个 AT URI 放入查询参数将涉及双重编码。没有明确可靠的方法知道输入字符串是否已被充分编码/解码。在构造字符串时很容易忘记编码。解码需要额外的字符串传递/复制,并且通常需要分配内存。太糟糕了。但我猜测标准人士会朝这个方向推动我们。 一类类似的方法是将 DID 语法映射到允许的 URI "主机"语法。例如,将冒号替换为破折号(`at://did-plc-abc123/...`),或发明新的主机名(`at://abc123.plc.did/...`)。这些看起来更清晰,并避免了一些编码问题,但它们增加了一层转换和间接性,这很可能会导致混淆。 一些人提议完全跳过 AT URI 方案,使用"DID URL",例如 `did:plc:vwzwgnygau7ed7b7wt5ux7y2/at/app.bsky.feed.post/3k5nobkf2w72g`。我不喜欢这样,因为在野外看到一个 DID URL 字符串时,解释方式不明确。你需要猜测它是"用于 atproto"的。这使得 URI 字符串更不易识别("这是干什么用的")。从长远来看,它也会将协议锁定为使用 DID,而我们将来可能希望支持非 DID 的持久账户标识符。 其他人提议始终在 AT URI 中使用句柄而不是 DID(`at://handle.example.com/...`)。这在 AT URI 规范中已经是允许的,并且遵循 IETF URI 规则。但这与 atproto 中 DID 的"持久标识符"优势相悖。句柄可以更改,但 DID 在账户的整个生命周期内保持不变。 我们可以停止在 URI 中使用 `//`,或者使用单斜杠(`at:/did:plc:abc123/...`)或不使用斜杠(`at:did:plc:abc123/...`)。我认为人们会经常把单斜杠版本输入或纠正为 `at://`。而无斜杠版本看起来更像 URN,可能会让新开发者或最终用户感到困惑。但我认为这些是在朝着正确的方向前进。 我目前选择的替代语法是使用空的 authority 部分和三个斜杠:`at:///did:plc:abc123/...`。这在 URI 规则下是允许的,并且经常出现在文件 URI(`file:///home/root/notes.txt`)中,其中 authority 部分是可选的。DID 最终位于第一个路径段中,不需要编码或篡改。常规的 URI/URL 库应该可以正常工作。将这种语法与当前 AT URI 区分开来很简单(只需检查字符串是否以 `at:///` 开头)。这只是一个字符的变化。 另一方面,这感觉像是在扭曲 URI 语法的精神:我们将"authority"部分移到"path"部分,仅仅是为了解决语法限制。我不确定 IETF 人员和 IANA URI 注册审查员会怎么想。它在视觉上看起来有点奇怪,人们很可能会手动将其"纠正"为双斜杠。 ## 还有别的吗?(https://bnewbold.leaflet.pub/3mph4hzvbdc2v#what-else) 这篇文章主要关注 AT URI 的主要用例:全局引用网络中的公共记录。但还有关于 atproto URI 的其他几件事值得注意。 AT URI 的一种简短形式用于 DID 文档中,以确认 DID/句柄映射。它们出现在 URI 的 "alsoKnownAs" 数组中,看起来像 `at://username.example.com`。句柄始终是有效的主机名,这意味着它们已经是有效的 URI(和 URL)。更改所有这些将需要广泛的 DID 文档更新,这将非常麻烦。我认为我们可以简单地为此用例保留这种语法,而不会造成太多混淆或中断。 目前正在进行 atproto 的"授权数据"设计工作。这不在当前 IETF 工作组的章程范围内,但我们预计它将在未来的重新章程中归入那里。当前"空间"提案的一部分将包括一个新的 `ats://` URI 方案("认证传输空间")。这个方案将具有与 `at://` 类似的语法,包括 URI authority 位置中的"空间授权 DID"。我们为 AT URI 提出的任何解决方案预计也将转移到 ATS URI。 IETF 工作组章程的一部分是制定"账户标识符系统"的标准和注册表。当前的 atproto 规范要求使用 DID,并且支持特定的两种 DID 方法(DID PLC 和 DID Web)。工作组可能会允许非 DID 标识符系统。总的来说,未来账户标识符的通用语法将与 AT URI 语法相关,并应作为最终标准的一部分包含在内。 我们还可以对 AT URI 做一些其他小改动,比如[blob 引用](https://leaflet.pub/3a68c557-f767-494b-81f9-b38c1a878a69)或[记录版本管理](https://leaflet.pub/4c5def15-d1f5-4476-a008-51176e615bc6)。这些都是相对简单的路径结构变化,不涉及这里 authority 部分语法的核心问题。 --- 以上就是大局!预计这将在接下来的几个月内在 IETF ATP 邮件列表和 atproto 开发者生态系统的其他地方进行讨论。如果能在年底前(也许是在 11 月的 IETF 127 会议上)达成粗略共识,那就太好了。

相似文章

DIDs 很酷,但我们并不需要它们

Hacker News Top

In a Moon 认为,尽管去中心化标识符(DID)在技术上是优雅的,但它们的用例并不需要它们——相反,选择了一个更简单的“主体”原语(命名空间:ID),该原语利用了已经嵌入在网页内容中的现有网络身份系统,例如 GitHub 用户名和电子邮件地址。

互操作性中的S

Lobsters Hottest

一篇博客文章,讨论了标准和互操作性的挑战,以子资源完整性(SRI)中一个耗时十年才浮现的base64编码错误为例,该错误最终导致了规范的更新。

ARIA、反模式与你

Lobsters Hottest

本文批评了ARIA和ARIA创作实践指南(APG)的误用,警告不要使用LLM代理从APG生成代码,并强调在可访问性方面应优先使用原生HTML而非ARIA。

避免在RSS中使用"<![CDATA[]]>"

Hacker News Top

本文认为,在RSS/Atom feed中使用CDATA区段存在问题,因为需要对']]>'序列进行特殊转义,建议改用标准XML转义以确保简单性和统一性。