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

如何使用 nginx 取得及提供 SXG 檔案,以及子資源預先載入的挑戰。

Hiroki Kumazaki
Hiroki Kumazaki

Signed HTTP Exchange (SXG) 發布商可以代表原創內容創作者提供 SXG 檔案。支援 SXG 的網頁瀏覽器會以原始內容創作者提供的形式顯示此類 SXG 檔案。這樣一來,您就能在不侵犯隱私權的情況下,實作跨網站預先載入功能。本指南說明如何正確發布 SXG。

跨瀏覽器支援

Chrome 目前是唯一支援 SXG 的瀏覽器。如需最新資訊,請參閱「原點簽署 HTTP 交換機制」一文的「共識與標準化」部分。

取得 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 連結會指向 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 工程師很樂意聽取您對 SXG 發布方式的意見回饋,歡迎來信至 webpackage-dev@chromium.org。您也可以加入規格討論,或向團隊回報錯誤。您的意見回饋將大大有助於標準化程序,並協助解決實作問題。感謝您!