[http] Last-Modified, If-Modified-Since, ETag 和 If-None-Match 介紹

在上一篇介紹了  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。

實際上的使用情境會像是以下步驟:

  1. client 發 request 與伺服器要 image.png 檔案

  2. server 回傳 Cache-Control: max-age=86400, no-cache ,  Last-Modified: Wed, 21 Oct 2018 07:28:00 GMT 及 image.png 檔案

  3. client 收到後將 image.png 存入 cache

  4. client 下次來訪網頁,再次要 image.png,因為 no-cache 所以需要做  revalidate,因此會發送 If-Modified-Since: Wed, 21 Oct 2018 07:28:00 GMT

  5. server 看檔案在 Wed, 21 Oct 2018 07:28:00 GMT 在這之後是否有被修改

  • 若有的話則回傳 200 及新檔案內容
  • 沒有的話則回傳 304(Not-Modified) 及空的 body
  1. 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。

實際上的使用情境會像是以下步驟:

  1. client 發 request 與伺服器要 image.png 檔案

  2. server 回傳 Cache-Control: max-age=86400, no-cache ,  ETag: “33a64df551425fcc55e4d42a148795d9f25f89d4” 及 image.png 檔案

  3. client 收到後將 image.png 存入 cache

  4. client 下次來訪網頁,再次要 image.png,因為 no-cache 所以需要做  revalidate,因此會發送 If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

  5. server 計算此檔案的 ETag 值是否有更改

  • 若有的話則回傳 200 及新檔案內容
  • 沒有的話則回傳 304(Not-Modified) 及空的 body
  1. 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

https://tools.ietf.org/html/rfc7232#section-2.2

https://tools.ietf.org/html/rfc7232#section-2.3

Leave a Reply