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<bool>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 #[serde(default)]
83 pub stale_if_error: Option<bool>,
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 && stale_while_revalidate
121 {
122 write!(cache_control, "stale-while-revalidate, ")?;
123 }
124 if let Some(private) = self.private
125 && private
126 {
127 write!(cache_control, "private, ")?;
128 }
129 if let Some(public) = self.public
130 && public
131 {
132 write!(cache_control, "public, ")?;
133 }
134 if let Some(immutable) = self.immutable
135 && immutable
136 {
137 write!(cache_control, "immutable, ")?;
138 }
139 if let Some(stale_if_error) = self.stale_if_error
140 && stale_if_error
141 {
142 write!(cache_control, "stale-if-error, ")?;
143 }
144
145 if cache_control.is_empty() {
146 cache_control.push_str(default);
147 } else {
148 cache_control.pop();
149 cache_control.pop();
150 }
151
152 Ok(())
153 }
154}
155
156#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
157#[cfg_attr(feature = "docs", derive(schemars::JsonSchema))]
158#[derive(Deserialize, Serialize, Debug, Clone, Default)]
159pub struct HttpCache {
160 #[serde(skip_serializing_if = "Option::is_none")]
161 #[serde(default)]
162 pub cache_control: Option<HttpCacheControl>,
163
164 #[serde(skip_serializing_if = "Option::is_none")]
169 #[serde(default)]
170 pub expires: Option<u64>,
171
172 #[serde(skip_serializing_if = "Option::is_none")]
173 #[serde(default)]
174 pub stored: Option<StoredCache>,
175
176 #[serde(skip_serializing_if = "Option::is_none")]
177 #[serde(default)]
178 pub etag: Option<HttpEtag>,
179}