1pub use http::Extensions;
18use log::warn;
19use once_cell::sync::{Lazy, OnceCell};
20use pingora_error::{Error, ErrorType::*, OrErr, Result};
21use pingora_header_serde::HeaderSerde;
22use pingora_http::{HMap, ResponseHeader};
23use serde::{Deserialize, Serialize};
24use std::borrow::Cow;
25use std::time::{Duration, SystemTime};
26
27use crate::key::HashBinary;
28
29pub(crate) type InternalMeta = internal_meta::InternalMetaLatest;
30mod internal_meta {
31 use super::*;
32
33 pub(crate) type InternalMetaLatest = InternalMetaV2;
34
35 #[derive(Debug, Deserialize, Serialize, Clone)]
36 pub(crate) struct InternalMetaV0 {
37 pub(crate) fresh_until: SystemTime,
38 pub(crate) created: SystemTime,
39 pub(crate) stale_while_revalidate_sec: u32,
40 pub(crate) stale_if_error_sec: u32,
41 }
43
44 impl InternalMetaV0 {
45 #[allow(dead_code)]
46 fn serialize(&self) -> Result<Vec<u8>> {
47 rmp_serde::encode::to_vec(self).or_err(InternalError, "failed to encode cache meta")
48 }
49
50 fn deserialize(buf: &[u8]) -> Result<Self> {
51 rmp_serde::decode::from_slice(buf)
52 .or_err(InternalError, "failed to decode cache meta v0")
53 }
54 }
55
56 #[derive(Debug, Deserialize, Serialize, Clone)]
57 pub(crate) struct InternalMetaV1 {
58 pub(crate) version: u8,
59 pub(crate) fresh_until: SystemTime,
60 pub(crate) created: SystemTime,
61 pub(crate) stale_while_revalidate_sec: u32,
62 pub(crate) stale_if_error_sec: u32,
63 }
65
66 impl InternalMetaV1 {
67 #[allow(dead_code)]
68 pub const VERSION: u8 = 1;
69
70 #[allow(dead_code)]
71 pub fn serialize(&self) -> Result<Vec<u8>> {
72 assert_eq!(self.version, 1);
73 rmp_serde::encode::to_vec(self).or_err(InternalError, "failed to encode cache meta")
74 }
75
76 fn deserialize(buf: &[u8]) -> Result<Self> {
77 rmp_serde::decode::from_slice(buf)
78 .or_err(InternalError, "failed to decode cache meta v1")
79 }
80 }
81
82 #[derive(Debug, Deserialize, Serialize, Clone)]
83 pub(crate) struct InternalMetaV2 {
84 pub(crate) version: u8,
85 pub(crate) fresh_until: SystemTime,
86 pub(crate) created: SystemTime,
87 pub(crate) updated: SystemTime,
88 pub(crate) stale_while_revalidate_sec: u32,
89 pub(crate) stale_if_error_sec: u32,
90 #[serde(default)]
96 pub(crate) variance: Option<HashBinary>,
97 #[serde(default)]
98 pub(crate) epoch_override: Option<SystemTime>,
99 #[serde(default)]
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub(crate) provenance: Option<SystemTime>,
104 }
105
106 impl Default for InternalMetaV2 {
107 fn default() -> Self {
108 let epoch = SystemTime::UNIX_EPOCH;
109 InternalMetaV2 {
110 version: InternalMetaV2::VERSION,
111 fresh_until: epoch,
112 created: epoch,
113 updated: epoch,
114 stale_while_revalidate_sec: 0,
115 stale_if_error_sec: 0,
116 variance: None,
117 epoch_override: None,
118 provenance: None,
119 }
120 }
121 }
122
123 impl InternalMetaV2 {
124 pub const VERSION: u8 = 2;
125
126 pub fn serialize(&self) -> Result<Vec<u8>> {
127 assert_eq!(self.version, Self::VERSION);
128 rmp_serde::encode::to_vec(self).or_err(InternalError, "failed to encode cache meta")
129 }
130
131 fn deserialize(buf: &[u8]) -> Result<Self> {
132 rmp_serde::decode::from_slice(buf)
133 .or_err(InternalError, "failed to decode cache meta v2")
134 }
135 }
136
137 impl From<InternalMetaV0> for InternalMetaV2 {
138 fn from(v0: InternalMetaV0) -> Self {
139 InternalMetaV2 {
140 version: InternalMetaV2::VERSION,
141 fresh_until: v0.fresh_until,
142 created: v0.created,
143 updated: v0.created,
144 stale_while_revalidate_sec: v0.stale_while_revalidate_sec,
145 stale_if_error_sec: v0.stale_if_error_sec,
146 ..Default::default()
147 }
148 }
149 }
150
151 impl From<InternalMetaV1> for InternalMetaV2 {
152 fn from(v1: InternalMetaV1) -> Self {
153 InternalMetaV2 {
154 version: InternalMetaV2::VERSION,
155 fresh_until: v1.fresh_until,
156 created: v1.created,
157 updated: v1.created,
158 stale_while_revalidate_sec: v1.stale_while_revalidate_sec,
159 stale_if_error_sec: v1.stale_if_error_sec,
160 ..Default::default()
161 }
162 }
163 }
164
165 pub(crate) fn deserialize(buf: &[u8]) -> Result<InternalMetaLatest> {
167 const MIN_SIZE: usize = 10; if buf.len() < MIN_SIZE {
169 return Error::e_explain(
170 InternalError,
171 format!("Buf too short ({}) to be InternalMeta", buf.len()),
172 );
173 }
174 let preread_buf = &mut &buf[..MIN_SIZE];
175 match rmp::decode::read_array_len(preread_buf)
177 .or_err(InternalError, "failed to decode cache meta array size")?
178 {
179 4 => Ok(InternalMetaV0::deserialize(buf)?.into()),
181 _ => {
183 let version = rmp::decode::read_pfix(preread_buf)
186 .or_err(InternalError, "failed to decode meta version")?;
187 match version {
188 1 => Ok(InternalMetaV1::deserialize(buf)?.into()),
189 2 => InternalMetaV2::deserialize(buf),
190 _ => Error::e_explain(
191 InternalError,
192 format!("Unknown InternalMeta version {version}"),
193 ),
194 }
195 }
196 }
197 }
198
199 #[cfg(test)]
200 mod tests {
201 use super::*;
202
203 #[test]
204 fn test_internal_meta_serde_v0() {
205 let meta = InternalMetaV0 {
206 fresh_until: SystemTime::now(),
207 created: SystemTime::now(),
208 stale_while_revalidate_sec: 0,
209 stale_if_error_sec: 0,
210 };
211 let binary = meta.serialize().unwrap();
212 let meta2 = InternalMetaV0::deserialize(&binary).unwrap();
213 assert_eq!(meta.fresh_until, meta2.fresh_until);
214 }
215
216 #[test]
217 fn test_internal_meta_serde_v1() {
218 let meta = InternalMetaV1 {
219 version: InternalMetaV1::VERSION,
220 fresh_until: SystemTime::now(),
221 created: SystemTime::now(),
222 stale_while_revalidate_sec: 0,
223 stale_if_error_sec: 0,
224 };
225 let binary = meta.serialize().unwrap();
226 let meta2 = InternalMetaV1::deserialize(&binary).unwrap();
227 assert_eq!(meta.fresh_until, meta2.fresh_until);
228 }
229
230 #[test]
231 fn test_internal_meta_serde_v2() {
232 let meta = InternalMetaV2::default();
233 let binary = meta.serialize().unwrap();
234 let meta2 = InternalMetaV2::deserialize(&binary).unwrap();
235 assert_eq!(meta2.version, 2);
236 assert_eq!(meta.fresh_until, meta2.fresh_until);
237 assert_eq!(meta.created, meta2.created);
238 assert_eq!(meta.updated, meta2.updated);
239 }
240
241 #[test]
242 fn test_internal_meta_serde_across_versions() {
243 let meta = InternalMetaV0 {
244 fresh_until: SystemTime::now(),
245 created: SystemTime::now(),
246 stale_while_revalidate_sec: 0,
247 stale_if_error_sec: 0,
248 };
249 let binary = meta.serialize().unwrap();
250 let meta2 = deserialize(&binary).unwrap();
251 assert_eq!(meta2.version, 2);
252 assert_eq!(meta.fresh_until, meta2.fresh_until);
253
254 let meta = InternalMetaV1 {
255 version: 1,
256 fresh_until: SystemTime::now(),
257 created: SystemTime::now(),
258 stale_while_revalidate_sec: 0,
259 stale_if_error_sec: 0,
260 };
261 let binary = meta.serialize().unwrap();
262 let meta2 = deserialize(&binary).unwrap();
263 assert_eq!(meta2.version, 2);
264 assert_eq!(meta.fresh_until, meta2.fresh_until);
265 assert_eq!(meta2.created, meta2.updated);
267 }
268
269 #[derive(Deserialize, Serialize)]
272 struct InternalMetaV2Base {
273 version: u8,
274 fresh_until: SystemTime,
275 created: SystemTime,
276 updated: SystemTime,
277 stale_while_revalidate_sec: u32,
278 stale_if_error_sec: u32,
279 }
280
281 impl InternalMetaV2Base {
282 pub const VERSION: u8 = 2;
283 pub fn serialize(&self) -> Result<Vec<u8>> {
284 assert!(self.version >= Self::VERSION);
285 rmp_serde::encode::to_vec(self).or_err(InternalError, "failed to encode cache meta")
286 }
287 fn deserialize(buf: &[u8]) -> Result<Self> {
288 rmp_serde::decode::from_slice(buf)
289 .or_err(InternalError, "failed to decode cache meta v2")
290 }
291 }
292
293 #[derive(Deserialize, Serialize)]
295 struct InternalMetaV2BaseWithVariance {
296 version: u8,
297 fresh_until: SystemTime,
298 created: SystemTime,
299 updated: SystemTime,
300 stale_while_revalidate_sec: u32,
301 stale_if_error_sec: u32,
302 #[serde(default)]
303 #[serde(skip_serializing_if = "Option::is_none")]
304 variance: Option<HashBinary>,
305 }
306
307 impl Default for InternalMetaV2BaseWithVariance {
308 fn default() -> Self {
309 let epoch = SystemTime::UNIX_EPOCH;
310 InternalMetaV2BaseWithVariance {
311 version: InternalMetaV2::VERSION,
312 fresh_until: epoch,
313 created: epoch,
314 updated: epoch,
315 stale_while_revalidate_sec: 0,
316 stale_if_error_sec: 0,
317 variance: None,
318 }
319 }
320 }
321
322 impl InternalMetaV2BaseWithVariance {
323 pub const VERSION: u8 = 2;
324 pub fn serialize(&self) -> Result<Vec<u8>> {
325 assert!(self.version >= Self::VERSION);
326 rmp_serde::encode::to_vec(self).or_err(InternalError, "failed to encode cache meta")
327 }
328 fn deserialize(buf: &[u8]) -> Result<Self> {
329 rmp_serde::decode::from_slice(buf)
330 .or_err(InternalError, "failed to decode cache meta v2")
331 }
332 }
333
334 #[derive(Deserialize, Serialize)]
338 struct InternalMetaV2BeforeProvenance {
339 version: u8,
340 fresh_until: SystemTime,
341 created: SystemTime,
342 updated: SystemTime,
343 stale_while_revalidate_sec: u32,
344 stale_if_error_sec: u32,
345 #[serde(default)]
346 variance: Option<HashBinary>,
347 #[serde(default)]
348 epoch_override: Option<SystemTime>,
349 }
350
351 impl Default for InternalMetaV2BeforeProvenance {
352 fn default() -> Self {
353 let epoch = SystemTime::UNIX_EPOCH;
354 InternalMetaV2BeforeProvenance {
355 version: InternalMetaV2::VERSION,
356 fresh_until: epoch,
357 created: epoch,
358 updated: epoch,
359 stale_while_revalidate_sec: 0,
360 stale_if_error_sec: 0,
361 variance: None,
362 epoch_override: None,
363 }
364 }
365 }
366
367 impl InternalMetaV2BeforeProvenance {
368 pub fn serialize(&self) -> Result<Vec<u8>> {
369 rmp_serde::encode::to_vec(self).or_err(InternalError, "failed to encode cache meta")
370 }
371 fn deserialize(buf: &[u8]) -> Result<Self> {
372 rmp_serde::decode::from_slice(buf)
373 .or_err(InternalError, "failed to decode cache meta v2")
374 }
375 }
376
377 #[test]
378 fn test_internal_meta_serde_v2_extend_fields_variance() {
379 let meta = InternalMetaV2BaseWithVariance::default();
381 let binary = meta.serialize().unwrap();
382 let meta2 = InternalMetaV2Base::deserialize(&binary).unwrap();
383 assert_eq!(meta2.version, 2);
384 assert_eq!(meta.fresh_until, meta2.fresh_until);
385 assert_eq!(meta.created, meta2.created);
386 assert_eq!(meta.updated, meta2.updated);
387
388 let now = SystemTime::now();
390 let meta = InternalMetaV2Base {
391 version: InternalMetaV2::VERSION,
392 fresh_until: now,
393 created: now,
394 updated: now,
395 stale_while_revalidate_sec: 0,
396 stale_if_error_sec: 0,
397 };
398 let binary = meta.serialize().unwrap();
399 let meta2 = InternalMetaV2BaseWithVariance::deserialize(&binary).unwrap();
400 assert_eq!(meta2.version, 2);
401 assert_eq!(meta.fresh_until, meta2.fresh_until);
402 assert_eq!(meta.created, meta2.created);
403 assert_eq!(meta.updated, meta2.updated);
404 }
405
406 #[test]
407 fn test_internal_meta_serde_v2_extend_fields_epoch_override() {
408 let now = SystemTime::now();
409
410 let mut meta = InternalMetaV2BaseWithVariance {
415 version: InternalMetaV2::VERSION,
416 fresh_until: now,
417 created: now,
418 updated: now,
419 stale_while_revalidate_sec: 0,
420 stale_if_error_sec: 0,
421 variance: None,
422 };
423 let binary = meta.serialize().unwrap();
424 let meta2 = InternalMetaV2::deserialize(&binary).unwrap();
425 assert_eq!(meta2.version, 2);
426 assert_eq!(meta.fresh_until, meta2.fresh_until);
427 assert_eq!(meta.created, meta2.created);
428 assert_eq!(meta.updated, meta2.updated);
429 assert!(meta2.variance.is_none());
430 assert!(meta2.epoch_override.is_none());
431
432 meta.variance = Some(*b"variance_testing");
434 let binary = meta.serialize().unwrap();
435 let meta2 = InternalMetaV2::deserialize(&binary).unwrap();
436 assert_eq!(meta2.version, 2);
437 assert_eq!(meta.fresh_until, meta2.fresh_until);
438 assert_eq!(meta.created, meta2.created);
439 assert_eq!(meta.updated, meta2.updated);
440 assert_eq!(meta.variance, meta2.variance);
441 assert!(meta2.epoch_override.is_none());
442 }
443
444 #[test]
449 fn test_internal_meta_serde_v2_epoch_override_always_serialized() {
450 let now = SystemTime::now();
451
452 let meta_none = InternalMetaV2 {
453 fresh_until: now,
454 created: now,
455 updated: now,
456 epoch_override: None,
457 ..Default::default()
458 };
459 let meta_some = InternalMetaV2 {
460 fresh_until: now,
461 created: now,
462 updated: now,
463 epoch_override: Some(now),
464 ..Default::default()
465 };
466
467 let bin_none = meta_none.serialize().unwrap();
468 let bin_some = meta_some.serialize().unwrap();
469
470 let len_none =
474 rmp::decode::read_array_len(&mut &bin_none[..]).expect("decode array len");
475 let len_some =
476 rmp::decode::read_array_len(&mut &bin_some[..]).expect("decode array len");
477 assert_eq!(len_none, len_some);
478
479 let decoded_none = InternalMetaV2::deserialize(&bin_none).unwrap();
481 let decoded_some = InternalMetaV2::deserialize(&bin_some).unwrap();
482 assert!(decoded_none.epoch_override.is_none());
483 assert_eq!(decoded_some.epoch_override, Some(now));
484
485 let meta_none_with_variance = InternalMetaV2 {
487 fresh_until: now,
488 created: now,
489 updated: now,
490 variance: Some(*b"variance_testing"),
491 epoch_override: None,
492 ..Default::default()
493 };
494 let meta_some_with_variance = InternalMetaV2 {
495 fresh_until: now,
496 created: now,
497 updated: now,
498 variance: Some(*b"variance_testing"),
499 epoch_override: Some(now),
500 ..Default::default()
501 };
502 let bin_none = meta_none_with_variance.serialize().unwrap();
503 let bin_some = meta_some_with_variance.serialize().unwrap();
504 let len_none =
505 rmp::decode::read_array_len(&mut &bin_none[..]).expect("decode array len");
506 let len_some =
507 rmp::decode::read_array_len(&mut &bin_some[..]).expect("decode array len");
508 assert_eq!(len_none, len_some);
509 }
510
511 #[test]
515 fn test_internal_meta_serde_v2_extend_fields_provenance_backward_compat() {
516 let now = SystemTime::now();
517 let old = InternalMetaV2BeforeProvenance {
518 fresh_until: now,
519 created: now,
520 updated: now,
521 variance: Some(*b"variance_testing"),
522 epoch_override: Some(now),
523 ..Default::default()
524 };
525 let binary = old.serialize().unwrap();
526
527 let decoded = InternalMetaV2::deserialize(&binary).unwrap();
528 assert_eq!(decoded.version, 2);
529 assert_eq!(decoded.fresh_until, now);
530 assert_eq!(decoded.created, now);
531 assert_eq!(decoded.variance, Some(*b"variance_testing"));
532 assert_eq!(decoded.epoch_override, Some(now));
533 assert!(decoded.provenance.is_none());
535 }
536
537 #[test]
542 fn test_internal_meta_serde_v2_extend_fields_provenance_forward_compat_none() {
543 let now = SystemTime::now();
544 let current = InternalMetaV2 {
545 fresh_until: now,
546 created: now,
547 updated: now,
548 variance: Some(*b"variance_testing"),
549 epoch_override: Some(now),
550 provenance: None,
551 ..Default::default()
552 };
553 let binary = current.serialize().unwrap();
554
555 let decoded = InternalMetaV2BeforeProvenance::deserialize(&binary).unwrap();
558 assert_eq!(decoded.fresh_until, now);
559 assert_eq!(decoded.created, now);
560 assert_eq!(decoded.variance, Some(*b"variance_testing"));
561 assert_eq!(decoded.epoch_override, Some(now));
562 }
563
564 #[test]
567 fn test_internal_meta_serde_v2_extend_fields_provenance_some_needs_field_support() {
568 let now = SystemTime::now();
569 let current = InternalMetaV2 {
570 fresh_until: now,
571 created: now,
572 updated: now,
573 variance: Some(*b"variance_testing"),
574 epoch_override: Some(now),
575 provenance: Some(now),
576 ..Default::default()
577 };
578 let binary = current.serialize().unwrap();
579
580 assert!(InternalMetaV2BeforeProvenance::deserialize(&binary).is_err());
581 let decoded = InternalMetaV2::deserialize(&binary).unwrap();
582 assert_eq!(decoded.provenance, Some(now));
583 }
584
585 #[test]
588 fn test_internal_meta_serde_v2_provenance_round_trip() {
589 let admission = SystemTime::now();
590 let updated = admission + Duration::from_secs(300);
591 let meta = InternalMetaV2 {
592 fresh_until: updated,
593 created: updated, updated,
595 provenance: Some(admission), ..Default::default()
597 };
598 let binary = meta.serialize().unwrap();
599 let decoded = InternalMetaV2::deserialize(&binary).unwrap();
600 assert_eq!(decoded.created, updated);
601 assert_eq!(decoded.provenance, Some(admission));
602 }
603 }
604}
605
606#[derive(Debug)]
607pub(crate) struct CacheMetaInner {
608 pub(crate) internal: InternalMeta,
610 pub(crate) header: ResponseHeader,
611 pub extensions: Extensions,
614}
615
616#[derive(Debug)]
618pub struct CacheMeta(pub(crate) Box<CacheMetaInner>);
619
620impl CacheMeta {
621 pub fn new(
623 fresh_until: SystemTime,
624 created: SystemTime,
625 stale_while_revalidate_sec: u32,
626 stale_if_error_sec: u32,
627 header: ResponseHeader,
628 ) -> CacheMeta {
629 CacheMeta(Box::new(CacheMetaInner {
630 internal: InternalMeta {
631 version: InternalMeta::VERSION,
632 fresh_until,
633 created,
634 updated: created, stale_while_revalidate_sec,
636 stale_if_error_sec,
637 provenance: Some(created),
638 ..Default::default()
639 },
640 header,
641 extensions: Extensions::new(),
642 }))
643 }
644
645 pub fn created(&self) -> SystemTime {
647 self.0.internal.created
648 }
649
650 pub fn updated(&self) -> SystemTime {
654 self.0.internal.updated
655 }
656
657 pub fn provenance(&self) -> SystemTime {
664 self.0
665 .internal
666 .provenance
667 .unwrap_or(self.0.internal.created)
668 }
669
670 pub(crate) fn set_provenance(&mut self, provenance: SystemTime) {
672 self.0.internal.provenance = Some(provenance);
673 }
674
675 pub(crate) fn reset_provenance_to_created(&mut self) {
677 self.0.internal.provenance = Some(self.0.internal.created);
678 }
679
680 #[cfg(test)]
685 pub(crate) fn provenance_raw(&self) -> Option<SystemTime> {
686 self.0.internal.provenance
687 }
688
689 pub fn epoch(&self) -> SystemTime {
694 self.0.internal.epoch_override.unwrap_or(self.updated())
695 }
696
697 pub fn epoch_override(&self) -> Option<SystemTime> {
699 self.0.internal.epoch_override
700 }
701
702 pub fn set_epoch_override(&mut self, epoch: SystemTime) {
707 self.0.internal.epoch_override = Some(epoch);
708 }
709
710 pub fn remove_epoch_override(&mut self) {
712 self.0.internal.epoch_override = None;
713 }
714
715 pub fn is_fresh(&self, time: SystemTime) -> bool {
717 self.0.internal.fresh_until >= time
719 }
720
721 pub fn fresh_sec(&self) -> u64 {
726 let reference = self.epoch();
730 self.0
731 .internal
732 .fresh_until
733 .duration_since(reference)
734 .map_or(0, |duration| duration.as_secs())
735 }
736
737 pub fn fresh_until(&self) -> SystemTime {
739 self.0.internal.fresh_until
740 }
741
742 pub fn age(&self) -> Duration {
746 let reference = self.epoch();
747 SystemTime::now()
748 .duration_since(reference)
749 .unwrap_or_default()
750 }
751
752 pub fn stale_while_revalidate_sec(&self) -> u32 {
754 self.0.internal.stale_while_revalidate_sec
755 }
756
757 pub fn stale_if_error_sec(&self) -> u32 {
759 self.0.internal.stale_if_error_sec
760 }
761
762 pub fn serve_stale_while_revalidate(&self, time: SystemTime) -> bool {
767 self.can_serve_stale(self.0.internal.stale_while_revalidate_sec, time)
768 }
769
770 pub fn serve_stale_if_error(&self, time: SystemTime) -> bool {
775 self.can_serve_stale(self.0.internal.stale_if_error_sec, time)
776 }
777
778 pub fn disable_serve_stale(&mut self) {
780 self.0.internal.stale_if_error_sec = 0;
781 self.0.internal.stale_while_revalidate_sec = 0;
782 }
783
784 pub fn expire_at(&mut self, instant: SystemTime) {
801 let fresh_until = &mut self.0.internal.fresh_until;
802 *fresh_until = (*fresh_until).min(instant);
803 }
804
805 pub fn update_freshness(
811 &mut self,
812 fresh_until: SystemTime,
813 stale_while_revalidate_sec: u32,
814 stale_if_error_sec: u32,
815 ) {
816 self.0.internal.fresh_until = fresh_until;
817 self.0.internal.stale_while_revalidate_sec = stale_while_revalidate_sec;
818 self.0.internal.stale_if_error_sec = stale_if_error_sec;
819 self.0.internal.updated = SystemTime::now();
820 }
821
822 pub fn variance(&self) -> Option<HashBinary> {
824 self.0.internal.variance
825 }
826
827 pub fn set_variance_key(&mut self, variance_key: HashBinary) {
829 self.0.internal.variance = Some(variance_key);
830 }
831
832 pub fn set_variance(&mut self, variance: HashBinary) {
834 self.0.internal.variance = Some(variance)
835 }
836
837 pub fn remove_variance(&mut self) {
839 self.0.internal.variance = None
840 }
841
842 pub fn response_header(&self) -> &ResponseHeader {
844 &self.0.header
845 }
846
847 pub fn response_header_mut(&mut self) -> &mut ResponseHeader {
849 &mut self.0.header
850 }
851
852 pub fn extensions(&self) -> &Extensions {
854 &self.0.extensions
855 }
856
857 pub fn extensions_mut(&mut self) -> &mut Extensions {
859 &mut self.0.extensions
860 }
861
862 pub fn response_header_copy(&self) -> ResponseHeader {
864 self.0.header.clone()
865 }
866
867 pub fn headers(&self) -> &HMap {
869 &self.0.header.headers
870 }
871
872 fn can_serve_stale(&self, serve_stale_sec: u32, time: SystemTime) -> bool {
873 if serve_stale_sec == 0 {
874 return false;
875 }
876 if let Some(stale_until) = self
877 .0
878 .internal
879 .fresh_until
880 .checked_add(Duration::from_secs(serve_stale_sec.into()))
881 {
882 stale_until >= time
883 } else {
884 true
886 }
887 }
888
889 pub fn serialize(&self) -> Result<(Vec<u8>, Vec<u8>)> {
891 let internal = self.0.internal.serialize()?;
892 let header = header_serialize(&self.0.header)?;
893 log::debug!("header to serialize: {:?}", self.0.header);
894 Ok((internal, header))
895 }
896
897 pub fn deserialize(internal: &[u8], header: &[u8]) -> Result<Self> {
899 let internal = internal_meta::deserialize(internal)?;
900 let header = header_deserialize(header)?;
901 Ok(CacheMeta(Box::new(CacheMetaInner {
902 internal,
903 header,
904 extensions: Extensions::new(),
905 })))
906 }
907}
908
909use http::StatusCode;
910
911pub type FreshDurationByStatusFn = fn(StatusCode) -> Option<Duration>;
913
914pub struct CacheMetaDefaults {
916 fresh_sec_fn: FreshDurationByStatusFn,
918 stale_while_revalidate_sec: u32,
919 stale_if_error_sec: u32,
921}
922
923impl CacheMetaDefaults {
924 pub const fn new(
926 fresh_sec_fn: FreshDurationByStatusFn,
927 stale_while_revalidate_sec: u32,
928 stale_if_error_sec: u32,
929 ) -> Self {
930 CacheMetaDefaults {
931 fresh_sec_fn,
932 stale_while_revalidate_sec,
933 stale_if_error_sec,
934 }
935 }
936
937 pub fn fresh_sec(&self, resp_status: StatusCode) -> Option<Duration> {
941 if resp_status == StatusCode::NOT_MODIFIED {
943 (self.fresh_sec_fn)(StatusCode::OK)
944 } else {
945 (self.fresh_sec_fn)(resp_status)
946 }
947 }
948
949 pub fn serve_stale_while_revalidate_sec(&self) -> u32 {
951 self.stale_while_revalidate_sec
952 }
953
954 pub fn serve_stale_if_error_sec(&self) -> u32 {
956 self.stale_if_error_sec
957 }
958}
959
960static COMPRESSION_DICT_CONTENT: OnceCell<Cow<'static, [u8]>> = OnceCell::new();
964
965static HEADER_SERDE: Lazy<HeaderSerde> = Lazy::new(|| {
966 let dict_opt = if let Some(dict_content) = COMPRESSION_DICT_CONTENT.get() {
967 Some(dict_content.to_vec())
968 } else {
969 warn!("no header compression dictionary loaded - use set_compression_dict_content() or set_compression_dict_path() to set one");
970 None
971 };
972
973 HeaderSerde::new(dict_opt)
974});
975
976pub(crate) fn header_serialize(header: &ResponseHeader) -> Result<Vec<u8>> {
977 HEADER_SERDE.serialize(header)
978}
979
980pub(crate) fn header_deserialize<T: AsRef<[u8]>>(buf: T) -> Result<ResponseHeader> {
981 HEADER_SERDE.deserialize(buf.as_ref())
982}
983
984pub fn set_compression_dict_path(path: &str) -> bool {
990 match std::fs::read(path) {
991 Ok(dict) => COMPRESSION_DICT_CONTENT.set(dict.into()).is_ok(),
992 Err(e) => {
993 warn!(
994 "failed to read header compress dictionary file at {}, {:?}",
995 path, e
996 );
997 false
998 }
999 }
1000}
1001
1002pub fn set_compression_dict_content(content: Cow<'static, [u8]>) -> bool {
1009 COMPRESSION_DICT_CONTENT.set(content).is_ok()
1010}
1011
1012#[cfg(test)]
1013mod tests {
1014 use super::*;
1015 use std::time::Duration;
1016
1017 #[test]
1018 fn test_cache_meta_age_without_override() {
1019 let now = SystemTime::now();
1020 let header = ResponseHeader::build_no_case(200, None).unwrap();
1021 let meta = CacheMeta::new(now + Duration::from_secs(300), now, 0, 0, header);
1022
1023 std::thread::sleep(Duration::from_millis(100));
1025 let age = meta.age();
1026 assert!(age.as_secs() < 1, "age should be close to 0");
1027
1028 assert_eq!(meta.epoch(), meta.updated());
1030 }
1031
1032 #[test]
1033 fn test_cache_meta_age_with_epoch_override_past() {
1034 let now = SystemTime::now();
1035 let header = ResponseHeader::build(200, None).unwrap();
1036 let mut meta = CacheMeta::new(now + Duration::from_secs(300), now, 0, 0, header);
1037
1038 let epoch_override = now - Duration::from_secs(10);
1040 meta.set_epoch_override(epoch_override);
1041
1042 let age = meta.age();
1044 assert!(age.as_secs() >= 10);
1045 assert!(age.as_secs() < 12);
1046
1047 assert_eq!(meta.epoch(), epoch_override);
1049 assert_eq!(meta.epoch_override(), Some(epoch_override));
1050 }
1051
1052 #[test]
1053 fn test_cache_meta_age_with_epoch_override_future() {
1054 let now = SystemTime::now();
1055 let header = ResponseHeader::build(200, None).unwrap();
1056 let mut meta = CacheMeta::new(now + Duration::from_secs(100), now, 0, 0, header);
1057
1058 let future_epoch = now + Duration::from_secs(10);
1060 meta.set_epoch_override(future_epoch);
1061
1062 let age_with_epoch = meta.age();
1063 assert_eq!(age_with_epoch, Duration::ZERO);
1065 }
1066
1067 #[test]
1068 fn test_cache_meta_fresh_sec() {
1069 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1070 let mut meta = CacheMeta::new(
1071 SystemTime::now() + Duration::from_secs(100),
1072 SystemTime::now() - Duration::from_secs(100),
1073 0,
1074 0,
1075 header,
1076 );
1077
1078 meta.0.internal.updated = SystemTime::UNIX_EPOCH + Duration::from_secs(1000);
1079 meta.0.internal.fresh_until = SystemTime::UNIX_EPOCH + Duration::from_secs(1100);
1080
1081 let fresh_sec_without_override = meta.fresh_sec();
1083 assert_eq!(fresh_sec_without_override, 100); let epoch_override = SystemTime::UNIX_EPOCH + Duration::from_secs(1050);
1087 meta.set_epoch_override(epoch_override);
1088 assert_eq!(meta.epoch_override(), Some(epoch_override));
1089 assert_eq!(meta.epoch(), epoch_override);
1090
1091 let fresh_sec_with_override = meta.fresh_sec();
1092 assert_eq!(fresh_sec_with_override, 50);
1094
1095 meta.remove_epoch_override();
1096 assert_eq!(meta.epoch_override(), None);
1097 assert_eq!(meta.epoch(), meta.updated());
1098 assert_eq!(meta.fresh_sec(), 100); }
1100
1101 #[test]
1102 fn test_cache_meta_new_stamps_provenance() {
1103 let now = SystemTime::now();
1104 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1105 let meta = CacheMeta::new(now + Duration::from_secs(60), now, 0, 0, header);
1106
1107 assert_eq!(meta.created(), now);
1108 assert_eq!(meta.provenance(), now);
1109 assert_eq!(meta.provenance_raw(), Some(now));
1110 }
1111
1112 #[test]
1113 fn test_cache_meta_provenance_fallback_for_absent_field() {
1114 let admission = SystemTime::now();
1115 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1116 let mut meta = CacheMeta::new(admission + Duration::from_secs(60), admission, 0, 0, header);
1117 meta.0.internal.provenance = None;
1118
1119 assert_eq!(meta.created(), admission);
1120 assert!(meta.provenance_raw().is_none());
1121 assert_eq!(meta.provenance(), admission);
1123 }
1124
1125 #[test]
1126 fn test_cache_meta_set_provenance() {
1127 let admission = SystemTime::now();
1128 let provenance = admission - Duration::from_secs(30);
1129 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1130 let mut meta = CacheMeta::new(admission + Duration::from_secs(60), admission, 0, 0, header);
1131
1132 meta.set_provenance(provenance);
1133
1134 assert_eq!(meta.created(), admission);
1135 assert_eq!(meta.provenance(), provenance);
1136 assert_eq!(meta.provenance_raw(), Some(provenance));
1137 }
1138
1139 #[test]
1140 fn expiring_at_the_current_instant_leaves_the_serve_stale_windows_open() {
1141 let admission = SystemTime::now();
1142 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1143 let mut meta = CacheMeta::new(
1144 admission + Duration::from_secs(300),
1145 admission,
1146 30,
1147 30,
1148 header,
1149 );
1150 assert!(meta.is_fresh(admission));
1151
1152 let expired_at = SystemTime::now();
1153 meta.expire_at(expired_at);
1154
1155 assert_eq!(meta.fresh_until(), expired_at);
1156 assert!(!meta.is_fresh(expired_at + Duration::from_secs(1)));
1157
1158 assert!(meta.serve_stale_while_revalidate(expired_at));
1161 assert!(meta.serve_stale_if_error(expired_at));
1162 }
1163
1164 #[test]
1167 fn expiring_at_an_instant_measures_the_serve_stale_windows_from_that_instant() {
1168 let admission = SystemTime::now();
1169 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1170 let mut meta = CacheMeta::new(
1171 admission + Duration::from_secs(3600),
1172 admission,
1173 600,
1174 600,
1175 header,
1176 );
1177
1178 let expired_at = admission + Duration::from_secs(300);
1179 meta.expire_at(expired_at);
1180
1181 assert_eq!(meta.fresh_until(), expired_at);
1182 assert!(!meta.is_fresh(expired_at + Duration::from_secs(1)));
1183
1184 assert!(meta.serve_stale_while_revalidate(expired_at + Duration::from_secs(599)));
1187 assert!(meta.serve_stale_if_error(expired_at + Duration::from_secs(599)));
1188 assert!(!meta.serve_stale_while_revalidate(expired_at + Duration::from_secs(601)));
1189 assert!(!meta.serve_stale_if_error(expired_at + Duration::from_secs(601)));
1190 }
1191
1192 #[test]
1195 fn expiring_at_an_instant_is_idempotent() {
1196 let admission = SystemTime::now();
1197 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1198 let mut meta = CacheMeta::new(
1199 admission + Duration::from_secs(3600),
1200 admission,
1201 600,
1202 600,
1203 header,
1204 );
1205
1206 let expired_at = admission + Duration::from_secs(300);
1207 meta.expire_at(expired_at);
1208 meta.expire_at(expired_at);
1209 meta.expire_at(expired_at);
1210
1211 assert_eq!(meta.fresh_until(), expired_at);
1212 assert!(!meta.serve_stale_while_revalidate(expired_at + Duration::from_secs(601)));
1213 }
1214
1215 #[test]
1217 fn expiring_at_a_later_instant_leaves_a_closed_window_closed() {
1218 let admission = SystemTime::now() - Duration::from_secs(3600);
1219 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1220 let fresh_until = admission + Duration::from_secs(60);
1221 let mut meta = CacheMeta::new(fresh_until, admission, 60, 60, header);
1222
1223 let now = SystemTime::now();
1224 assert!(!meta.serve_stale_while_revalidate(now));
1225
1226 meta.expire_at(now);
1227
1228 assert_eq!(
1229 meta.fresh_until(),
1230 fresh_until,
1231 "expiring later than the asset's own deadline must not move it"
1232 );
1233 assert!(!meta.serve_stale_while_revalidate(now));
1234 assert!(!meta.serve_stale_if_error(now));
1235 }
1236
1237 #[test]
1239 fn expiring_and_disabling_serve_stale_leaves_nothing_to_serve() {
1240 let admission = SystemTime::now();
1241 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1242 let mut meta = CacheMeta::new(
1243 admission + Duration::from_secs(300),
1244 admission,
1245 30,
1246 30,
1247 header,
1248 );
1249
1250 let expired_at = SystemTime::now();
1251 meta.expire_at(expired_at);
1252 meta.disable_serve_stale();
1253
1254 assert!(!meta.is_fresh(expired_at + Duration::from_secs(1)));
1255 assert!(!meta.serve_stale_while_revalidate(expired_at));
1256 assert!(!meta.serve_stale_if_error(expired_at));
1257 }
1258
1259 #[test]
1260 fn expiring_a_meta_leaves_its_admission_history_alone() {
1261 let admission = SystemTime::now() - Duration::from_secs(120);
1262 let provenance = admission - Duration::from_secs(30);
1263 let header = ResponseHeader::build(StatusCode::OK, None).unwrap();
1264 let mut meta = CacheMeta::new(
1265 admission + Duration::from_secs(300),
1266 admission,
1267 0,
1268 0,
1269 header,
1270 );
1271 meta.set_provenance(provenance);
1272
1273 meta.expire_at(SystemTime::now());
1274
1275 assert_eq!(meta.created(), admission);
1276 assert_eq!(meta.updated(), admission);
1277 assert_eq!(meta.provenance(), provenance);
1278 }
1279}