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

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

熊崎弘
Kuraki Kumazaki

Signed HTTP Exchange (SXG) 發布商,可以代表原始內容創作者提交 SXG 檔案。支援 SXG 的網路瀏覽器會顯示 SXG 檔案,就像是原始內容建立者所提供一樣。這樣一來,您就能在不違反隱私權的情況下,導入跨網站預先載入功能。本指南將說明如何正確發布 SXG。

跨瀏覽器支援

Chrome 是目前唯一支援 SXG 的瀏覽器。如需最新資訊,請參閱來源已簽署的 HTTP Exchange 的「共識與標準化」一節。

取得 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 中的 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 的意見。 您也可以參與規格討論,或向團隊回報錯誤。您的寶貴意見不僅有助於我們完成標準化程序,也有助於解決導入問題。 感謝!