use std::time::{Duration, SystemTime};
use http::HeaderValue;
use tokio::sync::watch;
#[derive(Clone)]
pub(crate) struct DateHeaderCache {
rx: watch::Receiver<HeaderValue>,
}
fn format_date_header() -> HeaderValue {
let now = SystemTime::now();
let formatted = httpdate::HttpDate::from(now).to_string();
HeaderValue::from_str(&formatted).unwrap()
}
impl DateHeaderCache {
pub fn start() -> Self {
let (tx, rx) = watch::channel(format_date_header());
tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(1));
loop {
interval.tick().await;
let _ = tx.send(format_date_header());
}
});
Self { rx }
}
pub fn header_value(&self) -> HeaderValue {
self.rx.borrow().clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_date_header_is_valid() {
let cache = DateHeaderCache::start();
let value = cache.header_value();
let s = value.to_str().unwrap();
assert!(s.contains("GMT"), "Date header should contain GMT: {}", s);
}
#[tokio::test]
async fn test_date_header_updates() {
let cache = DateHeaderCache::start();
let v1 = cache.header_value();
let v2 = cache.header_value();
assert_eq!(v1, v2);
}
}