在上一篇介紹了 http 關於 cache 的 header ,但當 cache 過期或是需要 revalidate 時又是如何運作的呢?
此篇將介紹幾個常見的 revalidate 的 http header
Last-Modified, If-Modified-Since (RFC 7232)
request
- If-Modified-Since: 上次
Last-Modifed
回傳的時間
用於做 revalidate 時,檢查檔案在指定時間後是否有被變更,若有回傳 200 及新的檔案內容,反之則回傳 304 (Not Modified) 即可。
response:
- Last-Modified: 檔案在伺服器最後修改的時間
在 response 帶回此檔案上次在伺服器被修改的時間,以備做 revalidate 時發送的 timestamp。
實際上的使用情境會像是以下步驟:
- client 發 request 與伺服器要
image.png
檔案 - server 回傳
Cache-Control: max-age=86400, no-cache
,Last-Modified: Wed, 21 Oct 2018 07:28:00 GMT
及image.png
檔案 - client 收到後將
image.png
存入 cache - client 下次來訪網頁,再次要
image.png
,因為no-cache
所以需要做 revalidate,因此會發送If-Modified-Since: Wed, 21 Oct 2018 07:28:00 GMT
- server 看檔案在
Wed, 21 Oct 2018 07:28:00 GMT
在這之後是否有被修改
- 若有的話則回傳 200 及新檔案內容
- 沒有的話則回傳 304(Not-Modified) 及空的 body
- client 若收到 200 則更新 cache, 反之則使用 cache 的檔案即可。
這樣就結束了 revalidate,可以看出這樣既檢查檔案修改時間也可以省下許多檔案(body)的流量。
優點
- 拿取伺服器檔案的修改時間,簡單快速
缺點
- 根據伺服器的絕對時間,若 web server 不只一台時,會有時間同步的問題
- 時間精準度只到秒,在秒內的修改不會正確更新
- 僅根據檔案修改的時間,無法判別檔案內容可能有修改
ETag, If-None-match (RFC 7232)
request:
- If-None-Match: 上次伺服器回傳的
ETag
用於做 revalidate 時,檢查內容的 hash 值是否有更改,若有回傳 200 及新的檔案內容,反之則回傳 304 (Not Modified) 即可。
response:
- ETag: 伺服器根據檔案內容 hash 的結果,此字串為 ascii 字元組成的字串即可
在 response 帶回此檔案 ETag 值,以備做 revalidate 時發送的 timestamp。
實際上的使用情境會像是以下步驟:
- client 發 request 與伺服器要
image.png
檔案 - server 回傳
Cache-Control: max-age=86400, no-cache
, ETag: “33a64df551425fcc55e4d42a148795d9f25f89d4” 及image.png
檔案 - client 收到後將
image.png
存入 cache - client 下次來訪網頁,再次要
image.png
,因為no-cache
所以需要做 revalidate,因此會發送If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
- server 計算此檔案的 ETag 值是否有更改
- 若有的話則回傳 200 及新檔案內容
- 沒有的話則回傳 304(Not-Modified) 及空的 body
- client 若收到 200 則更新 cache, 反之則使用 cache 的檔案即可。
這樣就結束了 revalidate,可以看出這樣既可以檢查檔案內容也可以省下許多檔案(body)的流量。
優點
- 客製 ETag 計算,如 apache 就提供 inode, last modified time, mtime 及 size 等等,簡單來說不容易 collision 的 hash function 都可以,較有彈性
- 可以自己決定 hash function,因此若設計得宜精準且正確性高
- 向下相容
Last-Modified
,如 nginx 預設是拿last modified time
來做ETag
缺點
- 可能導致伺服器負載變高,相依於 ETag 的 hash function
參考資料:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag