use crate::HeaderValue;
use std::{
cell::RefCell,
time::{SystemTime, UNIX_EPOCH},
};
thread_local! {
static CACHE: RefCell<Option<(u64, HeaderValue)>> = const { RefCell::new(None) };
}
pub(crate) fn current_date_header() -> HeaderValue {
let now = SystemTime::now();
let secs = now.duration_since(UNIX_EPOCH).map_or(0, |d| d.as_secs());
CACHE.with_borrow_mut(|cache| {
if let Some((cached_secs, value)) = cache
&& *cached_secs == secs
{
return value.clone();
}
let value = HeaderValue::from(httpdate::fmt_http_date(now));
*cache = Some((secs, value.clone()));
value
})
}
#[cfg(test)]
mod tests {
use super::*;
fn now_secs() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |d| d.as_secs())
}
#[test]
fn well_formed_and_cached_within_a_second() {
let before = now_secs();
let a = current_date_header();
let b = current_date_header();
let after = now_secs();
let s = a.as_str().expect("date is utf8");
assert_eq!(s.len(), 29, "IMF-fixdate is fixed-length");
assert!(s.ends_with(" GMT"), "got {s:?}");
if before == after {
assert_eq!(a, b);
}
}
}