WebKit 中的 URL 解析

现在是 2016 年。URL 已经被使用了几十年。你可能会认为它们的行为是一致的。但你会发现你是错的。

一致性

快速访问URL 构造函数一致性测试表明现代规范的一致性很差;目前没有哪款浏览器能通过超过约三分之二的测试,而且需要更多测试来涵盖更多边缘情况。目前在Safari Technology Preview中发布的 WebKit trunk 是所有主流浏览器引擎中最符合标准的 URL 解析器。

对于如此基础的互联网基础设施,浏览器之间的一致性至关重要,差异会以微妙的方式破坏 Web 应用程序。例如,new URL('file:afc') 在每个主流浏览器引擎中的行为都不同

  • 在 Safari 10 中,它被规范化为 file://afc
  • 在 Firefox 49 中,它被规范化为 file:///afc
  • 在 Chrome 53 中,它在 Windows 上被规范化为 file://afc/,在 macOS 上被规范化为 file:///afc
  • 在 Edge 38 中,它会抛出 JavaScript 异常

希望没有人依赖于这种格式错误的 URL 的一致行为,但浏览器之间存在许多此类差异。不幸的是,目前 Web 开发者采取的解决方案是避免使用在不同浏览器中行为不同的 URL。这种情况不应该发生。

然而,“正确”行为的定义是什么呢?如果具有市场份额的 URL 实现表现出某种特定行为,那么该行为就会成为事实标准,但互联网内部存在不同的市场。如果你运行一个可以通过 Web 浏览器访问的国际网络服务,那么具有大多数市场份额的浏览器是你最关心的。如果你的流量来自移动端,你会更关心浏览器在移动端的市场份额。如果你有一个使用操作系统 URL 实现的本地应用程序,你可能已经解决了该操作系统的怪癖,而操作系统的任何更改都可能破坏你的应用。

不幸的是,改变 URL 行为可能会破坏依赖现有怪癖的 Web 应用程序。例如,你可能试图通过删除 URL 中不必要的字符来减少服务器的带宽使用。如果你在向托管 https://example.org/ 的服务器发出请求时进行用户代理检查,并且对于基于 WebKit 的用户代理,使用了 <a href="https:/webkit.org"> 而不是 <a href="https://webkit.ac.cn">,那么 WebKit 变得更加符合标准将破坏你的链接。以前它会跳转到 https://webkit.ac.cn/,而现在它会跳转到 https://example.org/webkit.org,这与 Chrome、Firefox 和 URL 规范一致。如果你正在利用用户代理检查做一些技巧,你可以预料到你的 Web 应用程序会很脆弱,可能会随着浏览器的发展而损坏。

安全

浏览器不是唯一使用 URL 的程序。有许多广泛使用的 URL 解析器实现,例如WebKitChromiumGeckocURLPHPlibsoup等等,以及许多闭源实现。理想情况下,每个解析 URL 的程序行为都应该相同,以实现互操作性并谨慎处理无效输入。

HTTP 服务器通常看不到客户端的完整 URL。它们只在 HTTP 请求的第一行接收路径和查询,通常看起来像 GET /index.html?id=5 HTTP/1.1。服务器通常有不同类型的解析器,只解析路径和查询。服务器需要特别小心,不要假设路径没有尝试通过诸如 GET ../passwords.txt HTTP/1.1GET %2e%2e/passwords.txt HTTP/1.1 之类的请求访问文档根目录以外的文件,如果直接传递给文件系统,这可能会让攻击者访问私有文件。服务器还应警惕恶意客户端发送的非 ASCII 字符。

如果你的 Web 应用程序使用内容安全策略并以不同方式向同一主机发出请求,可能会出现意外的加载失败。例如,“http://example.com” 和 “http://ex%61mple.com” 应该相等,而 “http://[::0:abcd]” 和 “http://[::abcd]” 是相等的 IPv6 地址。不一致的主机解析会带来意外的安全隐患。

性能

URL 解析器的性能是一个重要的考量。URL 解析并不是很多应用中最慢的操作,但涉及 URL 解析的操作很多,因此加快 URL 解析速度会使许多操作稍微快一些。理想的基准测试会测量解析流行网站真实 URL 的性能,但发布此类基准测试存在问题,因为 URL 通常包含个人身份信息,例如 https://example.org/?user_id=57483。在这种基准测试中,WebKit trunk 的 URL 解析器比 Safari 10 中的 WebKit 快 20%。实际上,大部分时间花在解析 URL 的路径和查询上,它们通常最长且包含信息最多,以及主机,它需要最多的编码。目前,由于不同浏览器之间的行为差异太大,无法进行真正的“同类”URL 解析性能比较。

TL;DR

浏览器及其他地方的 URL 实现需要改变,变得更加一致和安全。Web 开发者需要适应这些变化。如果存在不同意见,我们应该讨论并解决它们。如果改变会破坏现有事物,我们应该考虑几十年后的互联网会是怎样。遵循 Web 标准会使互联网变得更好。

如果您有任何问题或意见,请通过@alexfchr联系我,或者联系 Apple Web 技术布道师 Jonathan Davis,地址是@jonathandavisweb-evangelist@apple.com