在“使用ETag跟蹤使用者”中有一點被忽略了,因為要用這張小圖統計統計uv, 所以要求瀏覽器必須每次都要傳送這個圖片的請求。這需要伺服器對圖片的快取策略做設定。

http/1.0 和 http/1.1 的快取策略不同,瀏覽器快取這事看似簡單,實際上很容易模稜兩可,造成疏忽。

HTTP/1.0

協議文件: https://www.w3.org/Protocols/HTTP/1.0/spec.html

相關欄位:

  • Date: 伺服器響應的時間
  • Expires: 資源過期時間
  • Last-Modified: 資源最後修改時間
  • If-Modified-Since: 用來驗證資源是否過期

策略:

如果Expires設定的時間在Date之後,則瀏覽器在Expires標記的時間之前都不會訪問伺服器了,而是使用瀏覽器快取,入下圖:

如果Expires設定的時間在Date之前,或者瀏覽器時間已經在Expires之後,那麼再次訪問圖片時, 瀏覽器就要向伺服器傳送請求,但不是重新拉取資料,而是詢問伺服器該資源是否過期,方法時,把上次response中Last-Modified的時間作為If-Modified-Since的時間,傳送請求,伺服器對比該時間和資源目前的更改時間,如果未更改,則返回304,否則傳輸新檔案,如下:

HTTP/1.1

HTTP/1.0快取機制完全依賴時間,弊端顯而易見,伺服器、客戶端的時鐘不同步,文件的 更新週期小於1s, 都會出現問題。

所以HTTP/1.1提倡的快取機制是,對比文件的hash值,文件內容變,則hash變,用相對時間代替絕對時間

協議文件:https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html

HTTP/1.1 繼承 HTTP/1.0 所以HTTP/1.0的相關欄位仍然有效,保留的這些欄位就是為了相容那些僅支援HTTP/1.0的客戶端。 HTTP/1.1伺服器不應該設定與1.0矛盾的過期策略, 1.1的伺服器在沒有文件hash值時,也可以使用If-Modified-Since進行判斷文件過期。

新增欄位:

Cache-Control最容易理解也是最常用的就是:

  • no-cache: 瀏覽器快取,但是認為是過期快取
  • no-store: 瀏覽器不快取
  • max-age:快取有效時間段

如果想要瀏覽器每次傳送請求,還啟用快取,那就使用Cache-Control: no-cache, 每次訪問圖片,瀏覽器都會去驗證Etag. 過程如下:

Nginx設定

最好的方法就是使用expires指令, 它兼顧1.1和1.0, 即所有的欄位都會給設定。但是nginx不支援ETag, 需要自己實現。 如果expires -1, 就是我需要的,瀏覽器既快取資料,但是每次訪問都請求伺服器。 詳見: http://nginx.org/en/docs/http/ngx_http_headers_module.html