過去沒太研究過HTTP,最近有空,看了一些。本文主要討論瀏覽器快取以及304狀態碼的一些知識,在這裡做一個分享,這裡先上一張HTTP請求流程圖:
一、詳細討論
1、是否禁止快取
禁止快取指的是快取中不得儲存任何關於客戶端請求和服務端響應的內容。每次由客戶端發起的請求都會下載完整的響應內容。
在請求頭中,Cache-Control: no-store
與Pragma: no-cache
都可以禁止快取,
但兩者也有區別,Pragma: no-cache
可以相容http 1.0
,而Cache-Control: no-store
是http 1.1
提供的。因此,Pragma: no-cache
可以應用到http 1.0
和http 1.1
,而Cache-Control: no-store
只能應用於http 1.1
。
2、是否檢查本地副本是否過期
是否檢查本地版本是否過期主要由Cache-Contro
的 no-cache
和must-revalidate
這兩個可選值控制,其中:
no-cache
: 告訴瀏覽器、快取伺服器,不管本地副本是否過期,使用資源副本前,一定要到源伺服器進行副本有效性校驗。must-revalidate
:告訴瀏覽器、快取伺服器,本地副本過期前,可以使用本地副本;本地副本一旦過期,必須去源伺服器進行有效性校驗。
3、本地副本是否過期
想要知道本地副本是否過期,我們就需要了解快取的過期機制:
(1)、過期機制中,最重要的指令是 max-age=<seconds>
,它表示資源能夠被緩的最大時間;它通常會和must-revalidate
一起使用,使用起來就像下面這樣:
Cache-Control: max-age=60, must-revalidate
複製程式碼
(2)、如果不含有max-age
屬性,則會去檢視是否包含Expires屬性,,通過比較Expires的值和頭裡面Date屬性的值來判斷是否快取還有效。
(3)、如果 max-age
和 expires
屬性都沒有,找找頭裡的 Last-Modified 資訊。如果有,快取的壽命就等於頭裡面 Date
的值減去Last-Modified
的值除以10(注:根據rfc2626其實也就是乘以10%)。
4、如果本地副本沒有過期
如果本地副本沒有過期,則會直接重快取中讀取資源,並返回200狀態碼。
5、如果本地副本過期
如果本地副本過期,則會進行到源伺服器進行有效性校驗的前期準備。
首先,會在請求頭裡尋找If-None-Match欄位,其值為伺服器上次返回的ETag響應頭的值:
如果請求頭裡沒有If-None-Match欄位,則會在請求頭中尋找If-Modified-Since欄位,其值為伺服器上次返回的Last-Modified響應頭中的日期值:
如果If-None-Match
與If-Modified-Since
都沒有,則會直接向伺服器請求資料。
6、到源伺服器進行有效性校驗
如果請求頭中帶有If-None-Match
或If-Modified-Since
,則會到源伺服器進行有效性校驗,如果源伺服器資源沒有變化,則會返回304;如果有變化,則返回200;
7、上述的一些流程還可以用下圖來表示
二、補充
私有快取和公共快取
在Cache-Control
還有兩個值:private
與public
,其中:
public
指令表示該響應可以被任何中間人(比如中間代理、CDN等)快取。若指定了 public
,則一些通常不被中間人快取的頁面(因為預設是 private
)(比如 帶有HTTP驗證資訊(帳號密碼)的頁面 或 某些特定影響狀態碼的頁面),將會被其快取。
而 private
則表示該響應是專用於某單個使用者的,中間人不能快取此響應,該響應只能應用於瀏覽器私有快取中。
三、參考文件
HTTP協議 MDN segmentfault網站上'趙雍'的回答 '紫雲飛'的部落格
原文地址 王玉略的個人網站