如何使用 nginx 發布 Signed HTTP Exchange (SXG)

如何使用 nginx 取得與提供 SXG 檔案,以及預先擷取子資源會遇到的挑戰。

Hiroki Kumazaki
Hiroki Kumazaki

身為 Signed HTTP Exchanges (SXG) 發布商,您可以代表原始內容創作者提交 SXG 檔案。支援 SXG 的網路瀏覽器會按照原內容創作者為來源提交這類 SXG 檔案。這可讓您在不侵犯隱私權的情況下,導入跨網站預先載入功能。本指南說明如何妥善發布 SXG。

跨瀏覽器支援

目前 Chrome 是唯一支援 SXG 的瀏覽器。查看共識與Origin-Signed HTTP Exchanges 的「標準化」部分以瞭解最新資訊。

取得 SXG 檔案

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.htmlindex.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 連結會指向 site.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 參照到 distributor.test/app.js 將指向 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 的意見回饋。 你也可以參與規格討論回報錯誤。 您的意見不但有助於標準化程序,也有助於解決導入問題。 感謝您!