skp_cache_http/
policy.rs

1use crate::CacheControl;
2use http::StatusCode;
3use std::time::Duration;
4
5/// Configuration for HTTP caching behavior
6#[derive(Debug, Clone, Default)]
7pub struct HttpCachePolicy {
8    /// Ignore Cache-Control from upstream?
9    pub ignore_upstream_cache_control: bool,
10    /// Default TTL if none specified
11    pub default_ttl: Option<Duration>,
12    /// Header names to include in Vary key
13    pub vary_headers: Vec<String>,
14    /// Bypass cache completely?
15    pub bypass: bool,
16    /// Tags to apply to cached entries (for invalidation)
17    pub tags: Vec<String>,
18}
19
20impl HttpCachePolicy {
21    pub fn new() -> Self {
22        Self::default()
23    }
24    
25    pub fn ttl(mut self, ttl: Duration) -> Self {
26        self.default_ttl = Some(ttl);
27        self
28    }
29    
30    pub fn vary_by(mut self, headers: &[&str]) -> Self {
31        self.vary_headers.extend(headers.iter().map(|s| s.to_string()));
32        self
33    }
34    
35    /// Calculate effective TTL based on policy and response headers
36    pub fn effective_ttl(&self, cc: &CacheControl) -> Option<Duration> {
37        if self.ignore_upstream_cache_control {
38             return self.default_ttl;
39        }
40        
41        // Priority: s-maxage > max-age > default
42        if let Some(ttl) = cc.s_maxage {
43             return Some(ttl);
44        }
45        if let Some(ttl) = cc.max_age {
46             return Some(ttl);
47        }
48        
49        self.default_ttl
50    }
51}
52
53/// Determine if a response is cacheable
54pub fn is_cacheable(status: StatusCode, cc: &CacheControl) -> bool {
55    // Only cache 200 OK for now
56    if status != StatusCode::OK {
57         return false;
58    }
59    
60    if cc.no_store { return false; }
61    
62    // Assuming shared cache semantics by default
63    if cc.private { 
64        return false; 
65    }
66    
67    true
68}