Cache-Control 標頭
HTTP Cache-Control 標頭在請求和響應中都包含指令(說明),用於控制瀏覽器和共享快取(例如代理、CDN)中的快取。
| 頭型別 | 請求標頭, 響應標頭 |
|---|---|
| 禁止請求頭 | 否 |
| CORS-safelisted 響應頭 | 是 |
語法
Cache-Control: <directive>, <directive>, ...
快取指令遵循以下規則
- 快取指令不區分大小寫。但是,建議使用小寫,因為某些實現不識別大寫指令。
- 允許多個指令,並且必須用逗號分隔(例如,
Cache-control: max-age=180, public)。 - 有些指令帶有一個可選引數。當提供引數時,它與指令名稱用等號(
=)分隔。通常,指令的引數是整數,因此不使用引號括起來(例如,Cache-control: max-age=12)。
快取指令
下表列出了標準的 Cache-Control 指令
| Request | Response |
|---|---|
max-age |
max-age |
max-stale |
- |
min-fresh |
- |
| - | s-maxage |
no-cache |
no-cache |
no-store |
no-store |
no-transform |
no-transform |
only-if-cached |
- |
| - | must-revalidate |
| - | proxy-revalidate |
| - | must-understand |
| - | private |
| - | public |
| - | immutable |
| - | stale-while-revalidate |
stale-if-error |
stale-if-error |
注意:請檢視相容性表以瞭解其支援情況;不識別它們的 user agent 應該忽略它們。
術語
本節定義了本文件中使用的術語,其中一些來自規範。
- (HTTP) 快取
-
儲存請求和響應以供後續請求重用的實現。它可以是共享快取,也可以是私有快取。
-
存在於源伺服器和客戶端之間的快取(例如代理、CDN)。它儲存單個響應並將其重用於多個使用者——因此開發人員應避免將個性化內容儲存在共享快取中。
- 私有快取
-
存在於客戶端中的快取。它也被稱為本地快取或瀏覽器快取。它可以為單個使用者儲存和重用個性化內容。
- 儲存響應
-
當響應可快取時,將響應儲存在快取中。但是,快取的響應並不總是按原樣重用。(通常,“快取”意味著儲存響應。)
- 重用響應
-
重用快取的響應以供後續請求。
- 重新驗證響應
-
詢問源伺服器儲存的響應是否仍然新鮮。通常,重新驗證透過條件請求完成。
- 新鮮響應
-
表示響應是新鮮的。這通常意味著可以根據請求指令將響應重用於後續請求。
- 陳舊響應
-
表示響應是陳舊響應。這通常意味著響應不能按原樣重用。快取儲存不需要立即刪除陳舊響應,因為重新驗證可以將響應從陳舊狀態更改為再次新鮮狀態。
- Age
-
自響應生成以來的時間。它是判斷響應是否新鮮或陳舊的標準。
指令
本節列出了影響快取的指令——包括響應指令和請求指令。
響應指令
max-age
max-age=N 響應指令表示響應在生成後 N 秒內保持新鮮。
Cache-Control: max-age=604800
表示快取在響應新鮮時可以儲存此響應並將其用於後續請求。
請注意,max-age 不是自收到響應以來的經過時間;它是自源伺服器生成響應以來的經過時間。因此,如果其他快取(在響應所走的網路路徑上)儲存響應 100 秒(使用 Age 響應標頭欄位指示),則瀏覽器快取將從其新鮮度生命週期中扣除 100 秒。
如果 max-age 值為負數(例如 -1)或不是整數(例如 3599.99),則快取行為未指定。鼓勵快取將該值視為 0(這在 HTTP 規範的計算新鮮度生命週期部分中提到)。
Cache-Control: max-age=604800
Age: 100
s-maxage
s-maxage 響應指令表示響應在共享快取中保持新鮮的時間。s-maxage 指令被私有快取忽略,如果存在,則會覆蓋 max-age 指令或 Expires 標頭為共享快取指定的值。
Cache-Control: s-maxage=604800
no-cache
no-cache 響應指令表示響應可以儲存在快取中,但在每次重用之前,即使快取與源伺服器斷開連線,也必須與源伺服器進行驗證。
Cache-Control: no-cache
如果您希望快取在重用儲存內容時始終檢查內容更新,則應使用 no-cache 指令。它透過要求快取重新驗證每個請求與源伺服器來實現此目的。
請注意,no-cache 並不意味著“不要快取”。no-cache 允許快取儲存響應,但要求它們在重用之前重新驗證。如果您想要的“不要快取”的含義實際上是“不要儲存”,那麼應使用 no-store 指令。
must-revalidate
must-revalidate 響應指令表示響應可以儲存在快取中,並且在新鮮時可以重用。如果響應變得陳舊,則在重用之前必須與源伺服器進行驗證。
通常,must-revalidate 與 max-age 一起使用。
Cache-Control: max-age=604800, must-revalidate
HTTP 允許快取在與源伺服器斷開連線時重用陳舊響應。must-revalidate 是一種防止這種情況發生的方法——儲存的響應要麼與源伺服器重新驗證,要麼生成 504(閘道器超時)響應。
proxy-revalidate
proxy-revalidate 響應指令等同於 must-revalidate,但專門用於共享快取。
no-store
no-store 響應指令表示任何型別的快取(私有或共享)都不應儲存此響應。
Cache-Control: no-store
private
private 響應指令表示響應只能儲存在私有快取中(例如,瀏覽器中的本地快取)。
Cache-Control: private
您應該為使用者個性化內容新增 private 指令,特別是對於登入後收到的響應和透過 Cookie 管理的會話。
如果您忘記為包含個性化內容的響應新增 private,則該響應可以儲存在共享快取中,並最終被多個使用者重用,這可能導致個人資訊洩露。
public
public 響應指令表示響應可以儲存在共享快取中。帶有 Authorization 標頭欄位的請求的響應不得儲存在共享快取中;但是,public 指令將導致此類響應儲存在共享快取中。
Cache-Control: public
通常,當頁面處於基本身份驗證或摘要身份驗證下時,瀏覽器會發送帶有 Authorization 標頭的請求。這意味著響應是針對受限使用者(擁有帳戶的使用者)進行訪問控制的,並且即使它具有 max-age,它也基本上不能被共享快取。
您可以使用 public 指令解除該限制。
Cache-Control: public, max-age=604800
請注意,s-maxage 或 must-revalidate 也會解除該限制。
如果請求沒有 Authorization 標頭,或者您已經在響應中使用了 s-maxage 或 must-revalidate,則無需使用 public。
must-understand
must-understand 響應指令表示快取應僅在它根據狀態碼理解快取要求的情況下儲存響應。
must-understand 應與 no-store 結合使用以實現回退行為。
Cache-Control: must-understand, no-store
如果快取不支援 must-understand,它將被忽略。如果 no-store 也存在,則不儲存響應。
如果快取支援 must-understand,它將儲存響應,同時理解基於其狀態碼的快取要求。
no-transform
一些中介軟體出於各種原因轉換內容。例如,一些中介軟體轉換影像以減小傳輸大小。在某些情況下,這對內容提供商來說是不希望的。
no-transform 表示任何中介軟體(無論它是否實現快取)都不應轉換響應內容。
immutable
immutable 響應指令表示響應在新鮮時不會更新。
Cache-Control: public, max-age=604800, immutable
靜態資源的一種現代最佳實踐是在其 URL 中包含版本/雜湊,同時從不修改資源——而是,在必要時,使用具有新版本號/雜湊的更新版本來更新資源,以便它們的 URL 不同。這被稱為快取失效模式。
<script src="https://example.com/react.0.0.0.js"></script>
當用戶重新載入瀏覽器時,瀏覽器將傳送條件請求以向源伺服器進行驗證。但是,即使使用者重新載入瀏覽器,也沒有必要重新驗證這些靜態資源,因為它們從未被修改。immutable 告訴快取響應在新鮮時是不可變的,並避免了對伺服器進行此類不必要的條件請求。
當您對資源使用快取失效模式並將其應用於長 max-age 時,您還可以新增 immutable 以避免重新驗證。
stale-while-revalidate
stale-while-revalidate 響應指令表示快取可以在重新驗證時重用陳舊響應。
Cache-Control: max-age=604800, stale-while-revalidate=86400
在上面的示例中,響應新鮮 7 天(604800 秒)。7 天后它會變得陳舊,但快取被允許在接下來的 1 天(86400 秒)內重用它,前提是它們在後臺重新驗證響應。
重新驗證將使快取再次新鮮,因此對客戶端來說,它在此期間始終是新鮮的——有效地向它們隱藏了重新驗證的延遲懲罰。
如果在此期間沒有發生請求,快取將變為陳舊,並且下一個請求將正常重新驗證。
stale-if-error
stale-if-error 響應指令表示當上遊伺服器生成錯誤或本地生成錯誤時,快取可以重用陳舊響應。在此處,錯誤被視為狀態碼為 500、502、503 或 504 的任何響應。
Cache-Control: max-age=604800, stale-if-error=86400
在上面的示例中,響應新鮮 7 天(604800 秒)。之後,它會變得陳舊,但在遇到錯誤時可以額外使用 1 天(86400 秒)。
在 stale-if-error 期限過後,客戶端將收到生成的任何錯誤。
請求指令
no-cache
no-cache 請求指令要求快取在重用之前與源伺服器驗證響應。
Cache-Control: no-cache
no-cache 允許客戶端即使快取有新鮮響應,也可以請求最新的響應。
當用戶強制重新載入頁面時,瀏覽器通常會在請求中新增 no-cache。
no-store
no-store 請求指令允許客戶端請求快取不要儲存請求和相應的響應——即使源伺服器的響應可以儲存。
Cache-Control: no-store
max-age
max-age=N 請求指令表示客戶端允許源伺服器在 N 秒內生成的儲存響應——其中 N 可以是任何非負整數(包括 0)。
Cache-Control: max-age=10800
在上述情況下,如果帶有 Cache-Control: max-age=10800 的響應是在 3 小時前生成的(根據 max-age 和 Age 標頭計算),則快取無法重用該響應。
許多瀏覽器使用此指令進行重新載入,如下所述。
Cache-Control: max-age=0
max-age=0 是 no-cache 的一種變通方法,因為許多舊(HTTP/1.0)快取實現不支援 no-cache。最近的瀏覽器在“重新載入”中仍然使用 max-age=0——為了向後相容——並且交替使用 no-cache 來導致“強制重新載入”。
如果 max-age 值為負數(例如 -1)或不是整數(例如 3599.99),則快取行為未指定。鼓勵快取將該值視為 0。
max-stale
max-stale=N 請求指令表示客戶端允許在 N 秒內陳舊的儲存響應。如果未指定 N 值,則客戶端將接受任何年齡的陳舊響應。
Cache-Control: max-stale=3600
例如,帶有上述標頭的請求表示瀏覽器將接受快取中在過去一小時內過期的陳舊響應。
當源伺服器宕機或太慢並且可以接受快取中即使有點舊的響應時,客戶端可以使用此標頭。
請注意,主流瀏覽器不支援帶有 max-stale 的請求。
min-fresh
min-fresh=N 請求指令表示客戶端允許至少在 N 秒內新鮮的儲存響應。
Cache-Control: min-fresh=600
在上述情況下,如果帶有 Cache-Control: max-age=3600 的響應在 51 分鐘前儲存在快取中,則快取無法重用該響應。
當用戶要求響應不僅新鮮,而且要求它在一段時間內不會更新時,客戶端可以使用此標頭。
請注意,主流瀏覽器不支援帶有 min-fresh 的請求。
no-transform
與 no-transform 對響應的含義相同,但用於請求。
only-if-cached
客戶端指示應返回已快取的響應。如果快取有儲存的響應,即使是陳舊的,也將返回。如果沒有可用的快取響應,將返回 504 閘道器超時響應。
stale-if-error
stale-if-error 請求指令表示瀏覽器有興趣在任何中間伺服器出錯時接收特定源的陳舊內容。這不受任何瀏覽器支援(請參閱瀏覽器相容性)。
使用案例
防止儲存
如果您不希望響應儲存在快取中,請使用 no-store 指令。
Cache-Control: no-store
請注意,no-cache 意味著“可以儲存,但在驗證之前不要重用”——因此它不是為了防止響應被儲存。
Cache-Control: no-cache
理論上,如果指令衝突,應遵守最嚴格的指令。因此,下面的示例基本上沒有意義,因為 private、no-cache、max-age=0 和 must-revalidate 與 no-store 衝突。
# conflicted
Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
# equivalent to
Cache-Control: no-store
使用“快取失效”快取靜態資產
當您使用版本控制/雜湊機制構建靜態資產時,將版本/雜湊新增到檔名或查詢字串是管理快取的好方法。
例如
<!-- index.html -->
<script src="/assets/react.min.js"></script>
<img src="/assets/hero.png" width="900" height="400" />
當您更新庫時,React 庫版本將更改,當您編輯圖片時,hero.png 也會更改。因此,它們很難用 max-age 儲存在快取中。
在這種情況下,您可以透過使用特定編號的庫版本並在其 URL 中包含圖片的雜湊來滿足快取需求。
<!-- index.html -->
<script src="/assets/react.0.0.0min.js"></script>
<img src="/assets/hero.png?hash=deadbeef" width="900" height="400" />
您可以新增一個長的 max-age 值和 immutable,因為內容永遠不會更改。
# /assets/*
Cache-Control: max-age=31536000, immutable
當您更新庫或編輯圖片時,新內容應具有新的 URL,並且快取不會重用。這被稱為“快取失效”模式。
使用 no-cache 確保 HTML 響應本身未被快取。no-cache 可能會導致重新驗證,並且客戶端將正確接收新版本的 HTML 響應和靜態資產。
# /index.html
Cache-Control: no-cache
注意:如果 index.html 受基本身份驗證或摘要身份驗證控制,則 /assets 下的檔案不會儲存在共享快取中。如果 /assets/ 檔案適合儲存在共享快取中,您還需要 public、s-maxage 或 must-revalidate 之一。
始終保持最新內容
對於動態生成或靜態但經常更新的內容,您希望使用者始終收到最新版本。
如果您不新增 Cache-Control 標頭,因為響應不打算快取,這可能會導致意外結果。快取儲存被允許啟發式地快取它——因此,如果您對快取有任何要求,您應該始終在 Cache-Control 標頭中明確指出它們。
向響應新增 no-cache 會導致對伺服器進行重新驗證,因此您每次都可以提供新鮮響應——或者如果客戶端已經有一個新響應,則只需響應 304 Not Modified。
Cache-Control: no-cache
大多數 HTTP/1.0 快取不支援 no-cache 指令,因此歷史上 max-age=0 被用作一種變通方法。但是,只有 max-age=0 可能會導致快取在與源伺服器斷開連線時重用陳舊響應。must-revalidate 解決了這個問題。這就是為什麼下面的示例等同於 no-cache。
Cache-Control: max-age=0, must-revalidate
但是現在,您可以簡單地使用 no-cache 來代替。
清除已儲存的快取
沒有快取指令可以清除中間伺服器上已儲存的響應。
想象一下,客戶端/快取儲存了一個路徑的新鮮響應,並且沒有向伺服器發出請求。伺服器無法對該路徑執行任何操作。
Clear-Site-Data: cache 可用於清除瀏覽器快取中站點的所有儲存響應,因此請謹慎使用。請注意,這不會影響共享或中間快取。
規範
| 規範 |
|---|
| HTTP 快取 # field.cache-control |
| HTTP 不可變響應 # the-immutable-cache-control-extension |
瀏覽器相容性
載入中…