use serve_net::Outcome;
use crate::RouteId;
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum CachePolicy {
#[default]
Unset,
NoStore,
Private {
max_age: u32,
},
Public {
max_age: u32,
},
Guests {
max_age: u32,
},
}
impl CachePolicy {
pub(crate) fn value(self, guest: bool) -> Option<String> {
match self {
Self::Unset => None,
Self::NoStore => Some("no-store".into()),
Self::Private { max_age } => Some(format!("private, max-age={max_age}")),
Self::Public { max_age } => Some(format!("public, max-age={max_age}")),
Self::Guests { max_age } if guest => Some(format!("public, max-age={max_age}")),
Self::Guests { .. } => Some("private, no-store".into()),
}
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum Cacheable {
#[default]
No,
Guests {
max_age: u32,
},
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Served {
pub outcome: Outcome,
pub route: Option<RouteId>,
pub cache: Cacheable,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Compression {
pub(crate) min_bytes: usize,
pub(crate) level: u8,
}
impl Default for Compression {
fn default() -> Self {
Self {
min_bytes: 1024,
level: 6,
}
}
}
impl Compression {
#[must_use]
pub fn min_bytes(mut self, bytes: usize) -> Self {
self.min_bytes = bytes;
self
}
#[must_use]
pub fn level(mut self, level: u8) -> Self {
self.level = level.clamp(1, 9);
self
}
}
pub(crate) fn compressible(content_type: &[u8]) -> bool {
let t = content_type.split(|&b| b == b';').next().unwrap_or(b"");
let t = t.trim_ascii();
t.starts_with(b"text/")
|| matches!(
t,
b"application/json"
| b"application/javascript"
| b"application/xml"
| b"application/manifest+json"
| b"application/rss+xml"
| b"application/atom+xml"
| b"image/svg+xml"
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_policy_values() {
assert_eq!(CachePolicy::Unset.value(true), None);
assert_eq!(
CachePolicy::Guests { max_age: 60 }.value(true).unwrap(),
"public, max-age=60"
);
assert_eq!(
CachePolicy::Guests { max_age: 60 }.value(false).unwrap(),
"private, no-store"
);
assert_eq!(
CachePolicy::Private { max_age: 5 }.value(false).unwrap(),
"private, max-age=5"
);
}
#[test]
fn test_compressible() {
assert!(compressible(b"text/html; charset=utf-8"));
assert!(compressible(b"application/json"));
assert!(!compressible(b"image/png"));
assert!(!compressible(b""));
}
}