tower_http/cors/
max_age.rs
1use std::{fmt, sync::Arc, time::Duration};
2
3use http::{
4 header::{self, HeaderName, HeaderValue},
5 request::Parts as RequestParts,
6};
7
8#[derive(Clone, Default)]
14#[must_use]
15pub struct MaxAge(MaxAgeInner);
16
17impl MaxAge {
18 pub fn exact(max_age: Duration) -> Self {
22 Self(MaxAgeInner::Exact(Some(max_age.as_secs().into())))
23 }
24
25 pub fn dynamic<F>(f: F) -> Self
29 where
30 F: Fn(&HeaderValue, &RequestParts) -> Duration + Send + Sync + 'static,
31 {
32 Self(MaxAgeInner::Fn(Arc::new(f)))
33 }
34
35 pub(super) fn to_header(
36 &self,
37 origin: Option<&HeaderValue>,
38 parts: &RequestParts,
39 ) -> Option<(HeaderName, HeaderValue)> {
40 let max_age = match &self.0 {
41 MaxAgeInner::Exact(v) => v.clone()?,
42 MaxAgeInner::Fn(c) => c(origin?, parts).as_secs().into(),
43 };
44
45 Some((header::ACCESS_CONTROL_MAX_AGE, max_age))
46 }
47}
48
49impl fmt::Debug for MaxAge {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match &self.0 {
52 MaxAgeInner::Exact(inner) => f.debug_tuple("Exact").field(inner).finish(),
53 MaxAgeInner::Fn(_) => f.debug_tuple("Fn").finish(),
54 }
55 }
56}
57
58impl From<Duration> for MaxAge {
59 fn from(max_age: Duration) -> Self {
60 Self::exact(max_age)
61 }
62}
63
64#[derive(Clone)]
65enum MaxAgeInner {
66 Exact(Option<HeaderValue>),
67 Fn(Arc<dyn for<'a> Fn(&'a HeaderValue, &'a RequestParts) -> Duration + Send + Sync + 'static>),
68}
69
70impl Default for MaxAgeInner {
71 fn default() -> Self {
72 Self::Exact(None)
73 }
74}