ordinary_config/http/
cache.rs1use crate::StoredCache;
6use serde::{Deserialize, Serialize};
7use std::fmt::Write;
8
9#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
10#[cfg_attr(feature = "docs", derive(schemars::JsonSchema))]
11#[derive(Deserialize, Serialize, Debug, Clone)]
12pub enum XXH3Variation {
13 Bit64,
14 Bit128,
15}
16
17#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
21#[cfg_attr(feature = "docs", derive(schemars::JsonSchema))]
22#[derive(Deserialize, Serialize, Debug, Clone)]
23pub enum HttpEtagAlgorithm {
24 AHash,
25 XXH3(XXH3Variation),
26 Rustc,
27 Blake3,
28 Foldhash,
29}
30
31#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
34#[cfg_attr(feature = "docs", derive(schemars::JsonSchema))]
35#[derive(Deserialize, Serialize, Debug, Clone)]
36pub struct HttpEtag {
37 #[serde(skip_serializing_if = "Option::is_none")]
38 #[serde(default)]
39 pub alg: Option<HttpEtagAlgorithm>,
40}
41
42#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
45#[cfg_attr(feature = "docs", derive(schemars::JsonSchema))]
46#[derive(Deserialize, Serialize, Debug, Clone, Default)]
47pub struct HttpCacheControl {
48 #[serde(skip_serializing_if = "Option::is_none")]
49 #[serde(default)]
50 pub max_age: Option<usize>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 #[serde(default)]
53 pub s_maxage: Option<usize>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 #[serde(default)]
56 pub no_cache: Option<bool>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 #[serde(default)]
59 pub no_store: Option<bool>,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 #[serde(default)]
62 pub no_transform: Option<bool>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 #[serde(default)]
65 pub must_revalidate: Option<bool>,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 #[serde(default)]
68 pub proxy_revalidate: Option<bool>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 #[serde(default)]
71 pub private: Option<bool>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 #[serde(default)]
74 pub public: Option<bool>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 #[serde(default)]
77 pub immutable: Option<bool>,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 #[serde(default)]
80 pub stale_while_revalidate: Option<usize>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 #[serde(default)]
83 pub stale_if_error: Option<usize>,
84}
85
86impl HttpCacheControl {
87 pub fn header_value(&self, cache_control: &mut String, default: &str) -> anyhow::Result<()> {
88 if let Some(max_age) = self.max_age {
89 write!(cache_control, "max-age={max_age}, ")?;
90 }
91 if let Some(s_maxage) = self.s_maxage {
92 write!(cache_control, "s-maxage={s_maxage}, ")?;
93 }
94 if let Some(no_cache) = self.no_cache
95 && no_cache
96 {
97 write!(cache_control, "no-cache, ")?;
98 }
99 if let Some(no_store) = self.no_store
100 && no_store
101 {
102 write!(cache_control, "no-store, ")?;
103 }
104 if let Some(no_transform) = self.no_transform
105 && no_transform
106 {
107 write!(cache_control, "no-transform, ")?;
108 }
109 if let Some(must_revalidate) = self.must_revalidate
110 && must_revalidate
111 {
112 write!(cache_control, "must-revalidate, ")?;
113 }
114 if let Some(proxy_revalidate) = self.proxy_revalidate
115 && proxy_revalidate
116 {
117 write!(cache_control, "proxy-revalidate, ")?;
118 }
119 if let Some(stale_while_revalidate) = self.stale_while_revalidate {
120 write!(
121 cache_control,
122 "stale-while-revalidate={stale_while_revalidate}, "
123 )?;
124 }
125 if let Some(private) = self.private
126 && private
127 {
128 write!(cache_control, "private, ")?;
129 }
130 if let Some(public) = self.public
131 && public
132 {
133 write!(cache_control, "public, ")?;
134 }
135 if let Some(immutable) = self.immutable
136 && immutable
137 {
138 write!(cache_control, "immutable, ")?;
139 }
140 if let Some(stale_if_error) = self.stale_if_error {
141 write!(cache_control, "stale-if-error={stale_if_error}, ")?;
142 }
143
144 if cache_control.is_empty() {
145 cache_control.push_str(default);
146 } else {
147 cache_control.pop();
148 cache_control.pop();
149 }
150
151 Ok(())
152 }
153}
154
155#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
156#[cfg_attr(feature = "docs", derive(schemars::JsonSchema))]
157#[derive(Deserialize, Serialize, Debug, Clone, Default)]
158pub struct HttpCache {
159 #[serde(skip_serializing_if = "Option::is_none")]
160 #[serde(default)]
161 pub cache_control: Option<HttpCacheControl>,
162
163 #[serde(skip_serializing_if = "Option::is_none")]
168 #[serde(default)]
169 pub expires: Option<u64>,
170
171 #[serde(skip_serializing_if = "Option::is_none")]
172 #[serde(default)]
173 pub stored: Option<StoredCache>,
174
175 #[serde(skip_serializing_if = "Option::is_none")]
176 #[serde(default)]
177 pub etag: Option<HttpEtag>,
178}