HTTP 協議的緩存機制涉及到多個請求頭字段,並且整個緩存機制的細節行爲也存在各類狀況的差別,譬如說何時訪問本地緩存不發送請求,何時發送請求查看資源是否更新,獲取 response 什麼狀況下更新緩存等。之前我對此只知其一;不知其二隻是籠統的知道一些概念,譬如 Cache-Control 能夠控制緩存的時間和是否須要緩存,可是緩存過時後的行爲,有緩存後瀏覽器是否有 http 請求都不甚瞭解。因此特意 google 下,此篇是對此的知識梳理。php
什麼狀況下可使用本地緩存?譬如說咱們用 get 方式請求了一個資源 http://mytest.domain.com/static/images/bg.png
,那麼咱們下次再請求這個圖片資源的時候符合哪些條件可使用本地緩存呢?html
http://mytest.domain.com/static/images/bg.png
,若是是 http://mytest.domain.com/static/images/bg.png?t=12312321
就會發起新的請求,由於 url 不一樣。注1:上述任何提一個條件均可以被 cache-control extension 覆蓋算法
注2:response header中不只僅能夠 Cache-Control: no-cache,還能夠 Cache-Control: no-cache="Set-Cookie" 詳見瀏覽器
瀏覽器是經過比較緩存剩餘有效時間和當前緩存已存在時間來判斷的:response_is_fresh = (freshness_lifetime > current_age)
。freshness_lifetime
取值優先級次序以下列表所示(排在上面的優先級越高):緩存
注1;若是有多個重複的上述頭,那麼是非法的,視做 response(資源)過時服務器
規範並無給出具體的算法,可是給出了最壞狀況(but does impose worst-case constraints on their results),若是 response(資源)有 Last-Modified 頭,那麼推薦用從當前到lastmodified這個時間段的 10% 做爲 freshness_lifetime
,而且 response(資源)的 current_age 若是已經超過24小時,必須在這個 response 上加上113 warn-code頭。不多有瀏覽器實現了freshness_lifetime
的自助計算(推測),因此仍是仍是鼓勵給出上述顯式的1 - 3三種狀況。網絡
泛泛來講就是 response(資源)在本地的駐足時間加上網絡傳輸時間,由於網絡傳輸時間的計算有多個條件,規範實在看的我頭暈,因此具體計算規則詳見規範dom
首先,若是第一次的 response(資源)頭中顯示申明瞭一些禁止緩存的頭(譬如:"no-store" or "no-cache" 等等),就不存在過時不過時的問題,由於這個資源不容許緩存。其次,過時緩存也不必定不可用,若是在斷網或者第二次請求帶上 max-stale 這個請求頭,那麼瀏覽器可使用過時的緩存(masx-stale 表示在緩存過時後多少時間內瀏覽器依然可使用緩存)。碰到過時緩存,瀏覽器能夠發送一個條件請求(conditional request)。這個請求的 url 依然是第一次請求的 url,只是會帶上些當前資源的一些信息,以供服務器驗證這個緩存是否依然可用仍是須要更新:google
服務器會根據不一樣的條件請求頭來驗證資源,具體的行爲詳見規範,這裏不細緻展開。針對條件請求,服務器返回會有三種狀況:url
若是是一個304的返回,規範說這個返回能夠更新本地緩存,更新策略分三種:
假設第一次請求一個資源,返回 header 裏面帶上以下字段:
Cache-Control: max-age=600
Last-Modified: Wed, 28 Aug 2013 10:36:42 GMT
ETag: "124752e0d85461a16e76fbdef2e84fb9"
拋開細枝末節的東西,那麼第二次請求一般大體流程圖以下:
當前資源緩存是否過時:response_is_fresh = (freshness_lifetime > current_age) | ----------------------------------- | | 是 否 | | 發送請求,帶上請求頭 從本地緩存中獲取資源(不發請求) If-Modified-Since: 此資源Last-Modified的值 If-None-Match: 此資源ETag的值 | 服務器根據 If-Modified-Since 和 If-None-Match 兩個值判斷資源是否更新過 | ------------------------- | | 是 否 | | 返回一個 status code:200 的 response 返回一個 status code:304 的 response response body 裏面是請求的資源 response body 爲空 | | 瀏覽器用 response body裏面的資源 依然從本地緩存裏面獲取資源 替換本地緩存中的資源
當你去瀏覽器驗證的時候可能會碰到一些特殊狀況,就是緩存有效,可是你刷新瀏覽器依然發送的條件請求。實際上是由於瀏覽器在請求頭中加入了一些料,譬如: Cache-Control: max-age=0。你刷新的方式能夠有不少種,譬如:按F5,按ctrl+F5,在地址欄按回車等等。這些不一樣的行爲都會影響瀏覽器發送請求的行爲。這裏有一些參考《在瀏覽器地址欄按回車、F五、Ctrl+F5刷新網頁的區別》