如何使用 nginx 分发 Signed HTTP Exchange (SXG)

如何使用 nginx 获取和分发 SXG 文件,以及子资源预提取的挑战。

Hiroki Kumazaki
Hiroki Kumazaki

作为 Signed HTTP Exchange (SXG) 分销商,您可以代表原始内容创作者提交 SXG 文件。支持 SXG 的网络浏览器会将此类 SXG 文件显示为来自原始内容创作者的文件。这样,您就可以在不侵犯隐私的情况下实现跨网站预加载。本指南介绍了如何正确分发 SXG。

Chrome 目前是唯一支持 SXG 的浏览器。如需了解最新信息,请参阅由源签名的 HTTP 交换的“共识和标准化”部分。

Accept 请求标头中指定您希望服务器随请求一起返回 SXG 文件:

Accept: application/signed-exchange;v=b3,*/*;q=0.8

本指南假定您将 SXG 文件放在 /var/www/sxg 中。

提供简单的 SXG 文件

若要分发单个 SXG 文件,请附加以下标头:

Content-Type: application/signed-exchange;v=v3
X-Content-Type-Options: nosniff

配置 nginx

http {
    ...
    types {
        application/signed-exchange;v=b3  sxg;
    }
    add_header X-Content-Type-Options nosniff;

    location / {
        more_set_headers "Content-Type: application/signed-exchange;v=b3";
        alias /var/www/sxg/;
        try_files $uri.sxg $uri =404;
        autoindex off;
    }
    ...

将新配置加载到 nginx 中:

sudo systemctl restart nginx.service

nginx 将开始投放 SXG 文件。 当 Chrome 访问您的服务器时,原始内容发布商的地址将显示在该栏中!

预提取子资源

大多数网页都由多个子资源组成,例如 CSS、JavaScript、字体和图片。如果没有内容创作者的私钥,则无法更改 SXG 的内容。 这会导致浏览器尝试解析子资源时出现问题。

例如,假设 https://website.test/index.html 中的 index.html.sxg 包含指向 https://website.test/app.js 的链接。当用户的浏览器从 https://distributor.test/example.com/index.html.sxg 收到 SXG 文件时,它会找到指向 https://website.test/app.js 的链接。浏览器可以在实际访问时直接提取 https://website.test/app.js,但为了保护隐私,不应在预加载阶段执行此操作。 如果在预加载阶段提取了资源,内容创作者 (website.test) 有可能检测到哪个内容分发方 (distributor.test) 正在请求该资源。

distributor.test/index.html.sxg 中指向 app.js 的链接指向 website.test/app.js。

如果分销商希望通过自己的服务提供 app.js.sxg,并尝试将 https://website.test/app.js 修改为分销商的该子资源版本(例如 https://distributor.test/website.test/app.js.sxg),则会导致签名不匹配,并使 SXG 无效。

尝试将 distributor.test/index.html.sxg 中对 app.js 的引用链接到 distributor.test/app.js 会导致签名不匹配。

为了解决这个问题,Chrome 现在提供了一项实验性 SXG 子资源预提取功能。您可以在 about://flags/#enable-sxg-subresource-prefetching 启用此功能。 如需使用子资源预提取功能,必须满足以下条件:

  • 发布商必须在 SXG 中嵌入响应标头条目,例如:link: <https://website.test/app.js>;rel="preload";as="script",<https://website.test/app.js>;rel="allowed-alt-sxg";header-integrity="sha256-h6GuCtTXe2nITIHHpJM+xCxcKrYDpOFcIXjihE4asxk="。这用于指定可替换为 SXG 的特定完整性哈希的子资源。
  • 分销商在分发 SXG 时必须附加响应标头,例如:link: <https://distributor.test/website.test/app.js.sxg>;rel="alternate";type="application/signed-exchange;v=b3";anchor="https://website.test/app.js"。这会指定 app.js 的路径,并与子资源相对应。

anchor

第一种比较简单,因为 nginx-sxg-module 可以计算完整性哈希值,并将其嵌入上游响应的链接标头中。但第二种方法更难,因为内容分销商必须知道 SXG 中的指定子资源。

如果除了 https://website.test/app.js 之外没有其他子资源,那么您只需在 nginx 配置中附加以下内容即可:

add_header link <https://distributor.test/website.test/app.js.sxg>;rel="alter...

但由于典型的网站包含大量子资源,因此这种情况很少见。此外,分销商在分发 SXG 文件时必须附加适当的锚链接标头。目前,没有简单的方法来解决此问题,敬请关注最新动态!

发送反馈

Chromium 工程师非常期待您通过 webpackage-dev@chromium.org 提供有关分发 SXG 的反馈。 您还可以加入规范讨论,或向团队报告 bug。 您的反馈将非常有助于完成标准化流程,并有助于解决实施问题。 谢谢!