use axum::http::{header, HeaderMap};
pub fn weak_etag(hash: &str) -> String {
format!("W/\"{hash}\"")
}
pub fn not_modified(req: &HeaderMap, etag: &str) -> bool {
let opaque = |t: &str| {
let t = t.trim();
t.strip_prefix("W/").unwrap_or(t).to_string()
};
let ours = opaque(etag);
req.get(header::IF_NONE_MATCH)
.and_then(|v| v.to_str().ok())
.is_some_and(|v| v.split(',').any(|t| t.trim() == "*" || opaque(t) == ours))
}
#[cfg(test)]
mod tests {
use super::*;
use axum::http::HeaderValue;
fn inm(v: &str) -> HeaderMap {
let mut h = HeaderMap::new();
h.insert(header::IF_NONE_MATCH, HeaderValue::from_str(v).unwrap());
h
}
#[test]
fn if_none_match_compares_weakly() {
let weak = weak_etag("abc123");
assert!(not_modified(&inm("\"abc123\""), &weak));
assert!(not_modified(&inm("\"x\", W/\"abc123\""), &weak));
assert!(not_modified(&inm("*"), &weak));
assert!(!not_modified(&inm("W/\"abc124\""), &weak));
assert!(!not_modified(&HeaderMap::new(), &weak));
let strong = "\"abc123\"";
assert!(not_modified(&inm("W/\"abc123\""), strong));
assert!(not_modified(&inm("\"a\", \"abc123\", \"b\""), strong));
assert!(!not_modified(&inm("\"abc\""), strong));
}
}