瀏覽器(Cache)的緩存邏輯(HTTP條件請求)
1. 瀏覽器緩存
一般來說,一個GET請求在目標資源存在的情況下會返回一個狀態碼為“200 OK”的響應,目標資源的內容將直接存放在響應報文的主體部分。如果資源的內容不會輕易改變,那么我們希望客戶端(如瀏覽器)在本地緩存獲取的資源。對于針對同一資源的后續請求來說,如果資源內容不曾改變,那么資源內容就無須再次作為網絡荷載予以響應。
確定資源是否發生變化可以采用兩種策略。第一種就是讓資源的提供者記錄最后一次更新資源的時間,資源的荷載內容(Payload)和這個時間戳將一并作為響應提供給作為請求發送者的客戶端。客戶端在緩存資源內容時也會保存這個時間戳。等到下次需要針對同一資源發送請求時,它會將這個時間戳一并發送出去,此時服務端就可以根據這個時間戳判斷目標資源在上次響應之后是否被修改過,然后做出針對性的響應。第二種是針對資源的內容生成一個“標簽”,標簽的一致性體現了資源內容的一致性,在HTTP規范中將這個標簽稱為ETag(Entity Tag)。
2. If-Modified-Since與If-None-Match
對于HTTP請求來說,緩存資源攜帶的最后修改時間戳和ETag分別保存在名為If-Modified-Since與If-None-Match的報頭中。報頭名稱體現的含義如下:只有目標資源在指定的時間之后被修改(If-Modified-Since)或者目前資源的狀態與提供的ETag不匹配(If-None-Match)的情況下才會返回資源的荷載內容。
以Chrome為例, 當服務端接收到針對某個資源的GET請求時,如果請求不具有上述這兩個報頭或者根據這兩個報頭攜帶的信息判斷資源已經發生改變,那么它返回一個狀態碼為“200 OK”的響應。除了將資源內容作為響應主體,如果能夠獲取到該資源最后一次修改的時間(一般精確到秒),那么格式化的時間戳還會通過一個名為Last-Modified的響應報頭提供給客戶端。針對資源自身內容生成的標簽,則會以ETag響應報頭的形式提供給客戶端。反之,如果做出相反的判斷,服務端就會返回一個狀態碼為“304 Not Modified”的響應,這個響應不包含主體內容。一般來說,這樣的響應也會攜帶Last-Modified報頭和ETag報頭。
3. Chrome

從Chrome的Network請求中可以看到,
- 發送的請求的Header中包含了
If-Modified-Since與If-None-Match; - 返回的內容,同樣會包含
Modified-Since與ETag; - 對于沒有內容更改的請求,Status Code為
304 - Not Modified - 對于304返回,
Modified-Since與ETag必然與請求的If-Modified-Since與If-None-Match分別一致;
4. 總結
- 客戶端(瀏覽器)如果有緩存內容,發送請求時會在Header中包含
If-Modified-Since與If-None-Match - 當服務器內容沒有修改時,服務器端會發送304給客戶端,這是body內容可能為空;
浙公網安備 33010602011771號