tower_http_cache/backend/
mod.rs1#[cfg(feature = "in-memory")]
13pub mod memory;
14pub mod multi_tier;
15#[cfg(feature = "redis-backend")]
16pub mod redis;
17
18use bytes::Bytes;
19use http::{HeaderName, HeaderValue, Response, StatusCode, Version};
20use std::future::Future;
21use std::time::{Duration, SystemTime};
22
23use crate::error::CacheError;
24use crate::layer::SyncBoxBody;
25
26#[derive(Debug, Clone)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct CacheEntry {
30 #[cfg_attr(feature = "serde", serde(with = "status_code_serde"))]
31 pub status: StatusCode,
32 #[cfg_attr(feature = "serde", serde(with = "version_serde"))]
33 pub version: Version,
34 pub headers: Vec<(String, Vec<u8>)>,
35 #[cfg_attr(feature = "serde", serde(with = "bytes_serde"))]
36 pub body: Bytes,
37 pub tags: Option<Vec<String>>,
38}
39
40#[cfg(feature = "serde")]
42mod status_code_serde {
43 use http::StatusCode;
44 use serde::{Deserialize, Deserializer, Serialize, Serializer};
45
46 pub fn serialize<S>(status: &StatusCode, serializer: S) -> Result<S::Ok, S::Error>
47 where
48 S: Serializer,
49 {
50 status.as_u16().serialize(serializer)
51 }
52
53 pub fn deserialize<'de, D>(deserializer: D) -> Result<StatusCode, D::Error>
54 where
55 D: Deserializer<'de>,
56 {
57 let code = u16::deserialize(deserializer)?;
58 StatusCode::from_u16(code).map_err(serde::de::Error::custom)
59 }
60}
61
62#[cfg(feature = "serde")]
63mod version_serde {
64 use http::Version;
65 use serde::{Deserialize, Deserializer, Serialize, Serializer};
66
67 pub fn serialize<S>(version: &Version, serializer: S) -> Result<S::Ok, S::Error>
68 where
69 S: Serializer,
70 {
71 let v: u8 = match *version {
76 Version::HTTP_09 => 0,
77 Version::HTTP_10 => 1,
78 Version::HTTP_11 => 2,
79 Version::HTTP_2 => 3,
80 Version::HTTP_3 => 4,
81 _ => 5,
82 };
83 v.serialize(serializer)
84 }
85
86 pub fn deserialize<'de, D>(deserializer: D) -> Result<Version, D::Error>
87 where
88 D: Deserializer<'de>,
89 {
90 let v = u8::deserialize(deserializer)?;
91 Ok(match v {
92 0 => Version::HTTP_09,
93 1 => Version::HTTP_10,
94 2 => Version::HTTP_11,
95 3 => Version::HTTP_2,
96 4 => Version::HTTP_3,
97 _ => Version::HTTP_11, })
99 }
100}
101
102#[cfg(feature = "serde")]
103mod bytes_serde {
104 use bytes::Bytes;
105 use serde::{Deserialize, Deserializer, Serializer};
106
107 pub fn serialize<S>(bytes: &Bytes, serializer: S) -> Result<S::Ok, S::Error>
108 where
109 S: Serializer,
110 {
111 serializer.serialize_bytes(bytes)
112 }
113
114 pub fn deserialize<'de, D>(deserializer: D) -> Result<Bytes, D::Error>
115 where
116 D: Deserializer<'de>,
117 {
118 let vec = Vec::<u8>::deserialize(deserializer)?;
119 Ok(Bytes::from(vec))
120 }
121}
122
123impl CacheEntry {
124 pub fn new(
129 status: StatusCode,
130 version: Version,
131 headers: Vec<(String, Vec<u8>)>,
132 body: Bytes,
133 ) -> Self {
134 Self {
135 status,
136 version,
137 headers,
138 body,
139 tags: None,
140 }
141 }
142
143 pub fn with_tags(mut self, tags: Vec<String>) -> Self {
145 self.tags = Some(tags);
146 self
147 }
148
149 pub fn into_response(self) -> Response<SyncBoxBody> {
151 use http_body_util::BodyExt;
152
153 let full_body = http_body_util::Full::from(self.body);
154 let boxed_body = full_body
155 .map_err(|never| -> Box<dyn std::error::Error + Send + Sync> { match never {} })
156 .boxed();
157
158 let mut response = Response::new(SyncBoxBody::new(boxed_body));
159 *response.status_mut() = self.status;
160 *response.version_mut() = self.version;
161
162 let headers = response.headers_mut();
163 headers.clear();
164 for (name, value) in self.headers {
165 if let (Ok(name), Ok(value)) = (
166 HeaderName::from_bytes(name.as_bytes()),
167 HeaderValue::from_bytes(&value),
168 ) {
169 headers.append(name, value);
170 }
171 }
172
173 response
174 }
175}
176
177#[derive(Debug, Clone)]
178pub struct CacheRead {
179 pub entry: CacheEntry,
181 pub expires_at: Option<SystemTime>,
182 pub stale_until: Option<SystemTime>,
183}
184
185pub trait CacheBackend: Send + Sync + Clone + 'static {
221 fn get(&self, key: &str) -> impl Future<Output = Result<Option<CacheRead>, CacheError>> + Send;
226
227 fn set(
229 &self,
230 key: String,
231 entry: CacheEntry,
232 ttl: Duration,
233 stale_for: Duration,
234 ) -> impl Future<Output = Result<(), CacheError>> + Send;
235
236 fn invalidate(&self, key: &str) -> impl Future<Output = Result<(), CacheError>> + Send;
238
239 fn get_keys_by_tag(
243 &self,
244 _tag: &str,
245 ) -> impl Future<Output = Result<Vec<String>, CacheError>> + Send {
246 async { Ok(Vec::new()) }
247 }
248
249 fn invalidate_by_tag(
253 &self,
254 tag: &str,
255 ) -> impl Future<Output = Result<usize, CacheError>> + Send {
256 async move {
257 let keys = self.get_keys_by_tag(tag).await?;
258 let count = keys.len();
259 for key in keys {
260 let _ = self.invalidate(&key).await;
261 }
262 Ok(count)
263 }
264 }
265
266 fn invalidate_by_tags(
270 &self,
271 tags: &[String],
272 ) -> impl Future<Output = Result<usize, CacheError>> + Send {
273 async move {
274 let mut total = 0;
275 for tag in tags {
276 total += self.invalidate_by_tag(tag).await?;
277 }
278 Ok(total)
279 }
280 }
281
282 fn list_tags(&self) -> impl Future<Output = Result<Vec<String>, CacheError>> + Send {
286 async { Ok(Vec::new()) }
287 }
288}