use reqwest::header::{CONTENT_LENGTH, CONTENT_TYPE, ETAG, HeaderMap, LAST_MODIFIED};
use std::time::SystemTime;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ResourceStats {
pub content_length: Option<u64>,
pub content_type: Option<String>,
pub last_modified: Option<SystemTime>,
pub etag: Option<String>,
}
impl ResourceStats {
pub fn from_headers(h: &HeaderMap) -> Self {
let content_length = h
.get(CONTENT_LENGTH)
.and_then(|v| v.to_str().ok())
.and_then(|s| s.parse::<u64>().ok());
let content_type = h
.get(CONTENT_TYPE)
.and_then(|v| v.to_str().ok())
.map(std::string::ToString::to_string);
let last_modified = h
.get(LAST_MODIFIED)
.and_then(|v| v.to_str().ok())
.and_then(|s| httpdate::parse_http_date(s).ok());
let etag = h.get(ETAG).and_then(|v| v.to_str().ok()).map(clean_etag);
Self {
content_length,
content_type,
last_modified,
etag,
}
}
}
fn clean_etag(raw: &str) -> String {
let s = raw.trim();
if s.starts_with("W/\"") && s.ends_with('"') && s.len() >= 4 {
return format!("W/{}", &s[3..s.len() - 1]);
}
if s.starts_with('"') && s.ends_with('"') && s.len() >= 2 {
return s[1..s.len() - 1].to_string();
}
s.to_string()
}