ETag
ETag
是 HTTP 回應標頭,用來標誌資源的版本。它可以使快取機制更有效率並節省頻寬,
畢竟資料沒有變動的話,伺服器就不需要再次傳回整份資料。
而且,它還可以用來預防多人同步更新資料時覆蓋掉彼此的資料("mid-air collisions")。
如果一個網址的資源有更新,就必須重新產生它的 Etag
值。
比較前後版本的 ETag 就能知道資源有沒有變化,所以 Etags 的作用就跟指紋一樣。有些伺服器便會把它用在追蹤用途上,而且可能會永久保存這些資訊。
Header type | Response header |
---|---|
Forbidden header name | no |
Syntax
ETag: W/"<etag_value>"
ETag: "<etag_value>"
Directives
W/
選擇性-
'W/'
(區分大小寫)表示資源使用 Weak etags。 Weak etags 很容易產生,但較不適合用在版本比對;Strong etags 很難有效率的產生,但很適合用在版本比對。 同一資源的兩個 weak etags 一致時,可以視為是同個版本,但其內容並非分毫不差。 比如說 weak etags 可以用在 byte range requests 上預防快取,不過帶有 strong etags 的請求仍然可能被快取住。 - "<etag_value>"
-
代表資源的版本。它的格式是由雙引號包著的 ASCII 字元組成的,像是:
"675af34563dc-tr34"
。 產生ETag
值的方式沒有一定。不過通常會是資料的 hash 值、最後修改時間的 hash 值,或者是版本號。 比如說,MDN 就是使用 wiki 文章的十六進位內文 hash 值。
範例
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" ETag: W/"0815"
避免空中碰撞
有了 ETag
以及 If-Match
標頭,你可以偵測空中碰撞。
比如說,在進入 wiki 編輯頁時,當下可以把內文的 hash 值放到 HTTP 回應中的 Etag
標頭:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
當儲存更新時, POST
請求就會有一個 If-Match
標頭,其值為 ETag
的值,這樣便可以用來檢查資料新鮮度。
If-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
如果 hash 沒有對上,就代表文件已經在你的編輯過程中,被別人先修改了,便會回傳
412
Precondition Failed
錯誤。
快取沒更新過的資源
另一個 ETag
標頭的好用處是用來快取沒更新過的資源。如果一位使用者再次造訪一個網址(而且前一次有設定 ETag
),而資源已經過期了(舊到不能用),
則客戶端會把 ETag
的值放在 If-None-Match
標頭內傳送:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
伺服器會比對客戶端傳來的 ETag
(放在 If-None-Match
標頭中) 與該資源在伺服器上的現有版本的 ETag
值,如果兩者一樣(代表沒更新過),
伺服器便會傳回 304
Not Modified
狀態且不帶資料,
這就可以讓客戶端知道自己快取住的版本仍然可用(可視為是新鮮的)。
規格
Specification |
---|
HTTP Semantics # field.etag |
瀏覽器相容性
BCD tables only load in the browser
See also
If-Match
If-None-Match
304
Not Modified
412
Precondition Failed
- W3C Note: Editing the Web – Detecting the Lost Update Problem Using Unreserved Checkout