Etag和if-None-Match

多芒小丸子發表於2018-09-16

前言

最近在跟後臺對介面時,發現請求同一個介面時總是一次成功一次失敗這樣間隔著來,很是困擾。請求失敗的時候報的錯時502 Not Modified,這個報錯也是百思不得解。在我掌握的知識裡502時伺服器錯誤,而Not Modified對應的狀態碼應該時304,但這樣的報錯提示是從來沒有遇到過。另外這個錯誤也只是在本地跑的時候會有,放到線上的環境就很正常,第二次請求時也是304而不會報錯。得閒我比較了本地兩次調介面時的請求頭,發現第二次也就是請求失敗的時候請求頭多了一個欄位If-None-Match,然後禁用了快取,果然就不會有報錯了,所以我猜想可能是後臺沒有對快取做處理吧。然後我去查閱資料學習了下請求頭ETagIf-Not-Match.

原理

它的原理是這樣的,當瀏覽器請求伺服器的某項資源(A)時, 伺服器根據A算出一個雜湊值(3f80f-1b6-3e1cb03b)並通過 ETag 返回給瀏覽器,瀏覽器把"3f80f-1b6-3e1cb03b" 和 A 同時快取在本地,當下次再次向伺服器請求A時,會通過類似 If-None-Match: "3f80f-1b6-3e1cb03b" 的請求頭把ETag傳送給伺服器,伺服器再次計算A的雜湊值並和瀏覽器返回的值做比較,如果發現A發生了變化就把A返回給瀏覽器(200),如果發現A沒有變化就給瀏覽器返回一個304未修改。這樣通過控制瀏覽器端的快取,可以節省伺服器的頻寬,因為伺服器不需要每次都把全量資料返回給客戶端。

Etag

首部欄位Etag能告知客戶端實體標識。它是一種可將資源以字串形式作為唯一性標識的方式。伺服器會為每份資源分配對應的ETag值。 當資源更新時,Etag的值也需要更新。生成Etag值時沒有統一的演算法規則,而僅僅是有伺服器來分配。

if-None-Match

首部欄位If-None-Match屬於附帶條件之一.

對於GET 和 HEAD 請求方法來說,當且僅當伺服器上沒有任何資源的 ETag 屬性值與這個首部中列出的相匹配的時候,伺服器端會才返回所請求的資源,響應碼為 200 .

對於 GET 和 HEAD 方法來說,當驗證失敗的時候,伺服器端必須返回響應碼 304 (Not Modified,未改變)。對於能夠引發伺服器狀態改變的方法,則返回 412 (Precondition Failed,前置條件失敗)。需要注意的是,伺服器端在生成狀態碼為 304 的響應的時候,必須同時生成以下會存在於對應的 200 響應中的首部:Cache-Control、Content-Location、Date、ETag、Expires 和 Vary 。

相關文章