如何使用 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。您也可以加入規格討論,或向團隊回報錯誤。您的意見回饋將大大有助於標準化程序,並協助解決實作問題。感謝您!