ETag是HTTP提供的快取機制,可以讓伺服器利用簡單的字串比對,來驗證客戶端先前快取到的HTTP回應是否依然有效。它的流程主要是這樣:伺服器在回應資料的同時,於HTTP回應標頭中夾帶ETag欄位,這個欄位的值就相當於這個資料的ID,而客戶端在將HTTP回應快取下來之後,若需重新發送請求時,就會在HTTP請求中夾帶If-None-Match欄位,將原先快取到的ETag值再回傳給伺服器,讓伺服器來判斷客戶端的快取是否需要更新。如果不需要,伺服器就會回傳304(Not Modified)這個HTTP狀態碼,讓客戶端繼續使用快取的資料;如果需要讓客戶端更新快取的話,就要再傳送一次完成的HTTP回應,並在HTTP標頭中夾帶新的ETag欄位值。



一個弱的(weak)ETag值長得像以下這樣:

W/"123456789"

一個強的(strong)ETag值長得像以下這樣:

"123456789"

強的ETag相比弱的ETag更可以保證兩個相同的ETag所對應到的是同一筆資料,以及兩個不同的ETag所對應到的是不同的資料。程式設計師應該自行判斷要用哪種比較合適。

Entity Tag

「Entity Tag」是筆者開發的套件,提供EntityTag結構體來解析ETag字串,在記憶體中表示ETag值,並提供相關的運算函數。

Crates.io

https://crates.io/crates/entity-tag

Cargo.toml

entity-tag = "*"

使用方法

entity_tag這個crate底下有EntityTag結構體。EntityTag結構體提供了with_strwith_stringfrom_strfrom_string關聯函數,可以解析ETag字串,建立EntityTag實體。

EntityTag結構體也有from_data關聯函數,可以直接傳入u8切片,藉由非常快速的ahash雜湊函數來計算出雜湊值,以建立出「強的」EntityTag實體。from_file_meta則是可以傳入std::fs::Metadata,藉由檔案的元數據(metadata)來快速建立出「弱的」EntityTag實體。

EntityTag實體可以使用strong_eqweak_eqstrong_neweak_ne方法來判斷是否和另一個EntityTag實體相等。

可參考以下程式碼:

use entity_tag::EntityTag;

let etag1 = EntityTag::with_str(true, "foo").unwrap();
let etag2 = EntityTag::from_str("\"foo\"").unwrap();

assert_eq!(true, etag1.weak);
assert_eq!(false, etag2.weak);

assert!(etag1.weak_eq(&etag2));
assert!(etag1.strong_ne(&etag2));

let etag3 = EntityTag::from_data(true, &[102, 111, 111]).unwrap();
assert_eq!("W/\"bp523oWgr0M\"", etag3.to_string());

let etag4 = EntityTag::from_file_meta(&std::fs::File::open("tests/data/P1060382.JPG").unwrap().metadata().unwrap());
println!("{}", etag4) // W/"CmgjkoKAfwQ"