HTTP 回應標頭 Vary 曾被稱為「HTTP 中最醜陋但尚未改進的部分」。它被形容為「糟糕且臃腫的機制」,在中介設備間的互通性也非常差。這通常讓理性的工程師望而卻步。

然而,醜陋不代表無用。

同一個 URL 可能有多個正確的回應。例如,伺服器可能會根據不同瀏覽器提供不同的圖片格式。如果快取忽略 Vary,可能會將錯誤的資料回應給請求端。但如果將每個原始標頭值都視為不同,少量相似請求就可能產生數千個幾乎無法重用的快取條目。Vary 告訴快取哪些請求欄位可能影響回應,但不告訴快取哪些差異真正重要。

現在,Vary 支援已在所有方案的 Cache Rules 中推出。來源伺服器仍會指定可能影響回應的請求標頭,但你可以決定 Cloudflare 如何處理每個標頭。你可以對已知的協商標頭進行規則化,當細微差異重要時則精確通過,或在變化過於不可預測時繞過快取。來源宣告可能變化的欄位,你決定哪些變化對快取真正有意義。

Vary 是一個標準的 HTTP 回應標頭,告訴中介快取(如 Cloudflare)哪些請求欄位可能影響來源伺服器的回應。網站利用 Vary 從同一 URL 提供不同語言、圖片格式、壓縮方式或區域內容。

舉例來說,一個 URL 可能產生兩種有效的表示。瀏覽器請求網頁時,來源回傳 HTML 並標示 Accept 為可能影響回應的欄位;API 用戶端則可能用不同的 Accept 請求同一 URL,這次正確回應是 JSON。Vary: Accept 告訴快取,僅 URL 不足以判斷回應,必須考慮請求的 Accept 值。

若無 Vary,快取中先進入的回應會被用於所有請求。若 HTML 先進入,API 用戶端會收到錯誤的標記語言,JSON 解析失敗;反之亦然。

Vary 防止快取將錯誤回應送給請求端,但也帶來更難的問題:當兩個請求的標頭值不同時,是否真的需要不同回應?

Vary 告訴快取哪些請求欄位可能影響回應,但不告訴快取回應的實際內容。例如,來源只提供英文、法文和德文內容,兩個請求都偏好英文,但排序和語言標籤不同。來源可能回傳相同的英文內容,但快取無法判斷兩者等價,可能將它們視為不同變體,導致快取條目分散,降低快取效率。

這是 Vary 的核心問題。應用程式通常從龐大的請求值集合中產生有限的表示。來源知道數千種語言偏好可以歸納為三種語言,但快取通常不懂。

結果是快取可能正確卻幾乎永遠冷卻(條目無法重用)。相同回應散布在多個流量不足以保持熱度的條目中,消耗容量、互相驅逐、降低快取命中率,並增加回源請求。驅逐可移除冷條目,但無法因回應相同而合併。

分析超過 1.2 億筆來自近 5 萬個熱門網站的回應,發現近 3,000 個網站在四個以上欄位使用 Vary,有些甚至多達 10、23 或 47 個欄位。我們希望確保客戶有工具在適當時使用 Vary,但不會造成無用快取。

部分高基數變化是刻意的。CDN 或反向代理可能注入地理區域等值,預測性地分割內容。這在可控且各組件對意義一致時有效。缺乏這些限制,快取會碎片化成永遠無法重用的變體。

這是我們設計時需解決的問題:保留足夠變化以提供正確回應,同時避免請求間偶然差異破壞快取效率。

Cloudflare 客戶已有多種處理類似 Vary 協商內容的方法:繞過快取讓來源處理、在自訂快取鍵或規則中複製來源協商邏輯、使用 Worker,或使用如圖片 Vary 等功能。

這些選項仍有用,但要麼放棄快取、複製應用邏輯、需額外編碼,或僅適用於較窄場景。Cache Rules 中的 Vary 可填補這些功能間的空白,將支援拆分為兩個決策:

Cache Rule 不會強制所有回應都變化。若來源未回傳 Vary,Cloudflare 正常快取回應,但規則仍可在轉發請求前重寫 Accept 和 Accept-Language。

當來源回傳 Vary,Cloudflare 會依設定對每個標頭採取行動。未個別設定的標頭使用規則預設行動。三種行動為:

1. 規則化(normalize):在選擇快取變體前規則化請求標頭,幫助等價請求共享快取回應。對 Accept、Accept-Language 和 Accept-Encoding 有專屬規則,其他標頭則修剪空白並合併重複行,保留大小寫和內部空白。建議用於多數請求值映射至少數回應的協商標頭。

2. 精確通過(passthrough):使用請求標頭原始位元組做快取匹配,保留大小寫、空白、順序和重複值。多行標頭以逗號合併匹配。輸出標頭行不變。Cloudflare 在禁用 Respect Strong ETags 時仍可重寫 Accept-Encoding。適用於值受控且精確值改變回應的標頭。

3. 繞過快取(bypass):當來源在 Vary 指定該標頭時,不快取回應。現有快取條目不會移除,需手動清除。

建議預設為規則化。個人化或無界值標頭用繞過,精確值影響回應用精確通過。

例如,精確通過保留大小寫、空白、順序和重複值的差異,即使來源視為等價。對 Vary: X-View 和精確通過,三個不同值會產生三個快取鍵。

過多偶然變化會將可重用回應拆成多個獨立變體。

無論設定如何,Vary: * 總是繞過快取,表示請求任何面向(甚至 HTTP 訊息外,如客戶端 IP)都可能影響來源回應,Cloudflare 因此無法重用回應。

以 /catalog 請求為例,首次請求時 Cloudflare 無 Vary 資料,快取未命中。匹配的 Cache Rule 可先規則化欄位,再向來源發送請求。

此步驟在 Cloudflare 知道回應是否含 Vary 前發生。Cache Rule 定義允許的規則化,回應決定這些欄位是否成為快取變體的一部分。

此順序很重要。若 Cloudflare 將多個原始值歸為一個規則化快取鍵,但來源仍收到原始值,來源可能產生不同回應,快取卻視為相同。轉發規則化值可保持來源選擇與快取匹配一致。

Cloudflare 記錄這些標頭名稱並將回應存為快取變體。標頭值依 Cache Rule 處理,區分同一資源的不同變體。

後續 /catalog 請求時,Cloudflare 從資源基礎快取鍵(通常是 URL 加其他設定欄位)開始,讀取已存 Vary 欄位,並對新請求的這些標頭套用 Cache Rule,找出匹配的快取變體。

Cloudflare 直接用這些值查找匹配快取變體,不會一一比對所有存儲變體。

若匹配且新鮮,為快取命中;否則向來源發送請求,並可能存為新變體。

來源回應完成循環。對 Vary 指定的每個標頭,Cloudflare 使用該標頭的設定行動,未個別設定則用規則預設行動。

這對來源提出重要責任。所有可快取且可能因請求欄位不同而異的回應,必須一致回傳適當的 Vary 標頭,包括錯誤和備援回應。若有回應遺漏,Cloudflare 可能快取該回應卻缺少必要變異,導致隔離失效。

快取鍵圖示為概念性。後續請求假設快取回應仍新鮮。

針對快取資源的清除會涵蓋所有 Vary 變體。自訂快取鍵清除規則仍適用。

變更 Vary 設定不會自動清除現有內容。新政策可能產生不同快取鍵,請求可能錯過並以新鍵重新填充,舊條目則待過期或手動清除。

回到前述請求偏好英文和法文的例子,兩者都偏好英文,但精確通過會視為不同變體。若 Cache Rule 允許 en、fr、de,規則化會將兩者都簡化為 en、fr,讓它們共享快取回應。

Cloudflare 會將 Accept、Accept-Language 和 Accept-Encoding 的值轉為小寫,依品質值排序(最高優先),並以字母序解決平手。客戶端排序不影響快取鍵。排序後,Cloudflare 會移除非零品質值條目的參數,縮短語言標籤或過濾至設定格式和語言時可能丟失 q=0(不可接受)。例如 en-US;q=0 會變成 en。如來源需看到這些排除,請用精確通過。

你也可設定規則只保留 Accept 和 Accept-Language 中指定的媒體類型或語言。區域語言標籤如 en-US 會簡化為基底語言 en,除非設定完整標籤。這讓你能將規則化與來源實際提供的格式和語言對齊。

為保持來源選擇與快取匹配一致,Cloudflare 會將規則化的 Accept 和 Accept-Language 轉發給來源。啟用 Respect Strong ETags 時,也會轉發規則化的 Accept-Encoding。其他標頭僅用於快取匹配時規則化。

在 Cloudflare 控制台,前往 Caching > Cache Rules,建立或編輯規則,使回應符合快取資格,並新增 Vary 設定。設定預設行為,然後加入來源預期指定的標頭。

相同設定也可透過 Rulesets API 在 http_request_cache_settings 階段使用。預設設定會為未個別設定但來源在 Vary 指定的標頭選擇後備行動。

此範例將 Accept 和 Accept-Language 規則化至設定的格式和語言集合。預設規則化行動也適用於 Vary 中指定的其他標頭。

這是一個完整的 PUT 請求主體,針對 http_request_cache_settings 階段入口。PUT 會取代該入口的所有規則。若已有 Cache Rules,請將它們包含在 rules 陣列中,或使用適當的單規則建立或更新操作。

若來源對每種媒體類型和語言組合只提供一種表示,則有六種內容組合。這不代表快取鍵上限為六。偏好順序、缺失標頭及規則化後為空的值會產生更多。保持支援集合小且明確規則邊界。部署後,使用不同標頭值測試同一 URL,應規則化至相同快取變體。從同一客戶端發送測試請求,確認回傳格式和語言正確,並檢查 CF-Cache-Status。快取填充後應有命中,持續未命中或意外繞過需調查。

更多限制、範例及 Terraform 設定,請參考 Vary 文件。

此時,明顯問題是:「為何不將 Accept 和 Accept-Language 加入自訂快取鍵?」

當這些欄位始終是資源身份的一部分時,這是可行的。但自訂快取鍵會將設定的維度加到規則涵蓋的所有回應,不論來源是否使用它們。

Vary 是回應驅動,快取鍵下的可快取回應需有一致的 Vary 欄位集合。

當請求屬性始終定義資源時,使用自訂快取鍵;當來源在可快取回應中宣告相同請求欄位時,使用 Vary。避免同時在兩者放置相同標頭,除非經過刻意設計和測試。

Vary 解決了一個明顯問題:一個 URL 可有多個正確回應。但它也帶給快取一個更難的問題:哪些請求差異真正重要?來源知道可提供哪些回應,快取需知道哪些請求可重用回應。

Cache Rules 中的 Vary 連結了這兩個視角。來源識別可能影響回應的請求欄位,你決定是否規則化值、精確通過差異,或將回應排除快取。

Vary 從未醜陋到無用。但手動設定支援格式和語言可能不適合所有應用。我們正在評估是否可借鑑已過期的 Availability Hints 草案,讓來源直接描述其提供的表示,減少設定工作。

Cache Rules 中的 Vary 已在免費、專業、商業及企業方案透過 Cloudflare 控制台、Rulesets API 和 Terraform 提供。

Cloudflare 推出對 HTTP Vary 標頭的支援,提升快取效率Cloudflare 推出對 HTTP Vary 標頭的支援,提升快取效率Cloudflare 推出對 HTTP Vary 標頭的支援,提升快取效率Cloudflare 推出對 HTTP Vary 標頭的支援,提升快取效率Cloudflare 推出對 HTTP Vary 標頭的支援,提升快取效率Cloudflare 推出對 HTTP Vary 標頭的支援,提升快取效率