async_graphql/registry/cache_control.rs
1/// Cache control value
2///
3/// # Examples
4///
5/// ```rust
6/// use async_graphql::*;
7///
8/// struct Query;
9///
10/// #[Object(cache_control(max_age = 60))]
11/// impl Query {
12/// #[graphql(cache_control(max_age = 30))]
13/// async fn value1(&self) -> i32 {
14/// 0
15/// }
16///
17/// #[graphql(cache_control(private))]
18/// async fn value2(&self) -> i32 {
19/// 0
20/// }
21///
22/// #[graphql(cache_control(no_cache))]
23/// async fn value3(&self) -> i32 {
24/// 0
25/// }
26/// }
27///
28/// # tokio::runtime::Runtime::new().unwrap().block_on(async {
29/// let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
30/// assert_eq!(
31/// schema
32/// .execute("{ value1 }")
33/// .await
34/// .into_result()
35/// .unwrap()
36/// .cache_control,
37/// CacheControl {
38/// public: true,
39/// max_age: 30
40/// }
41/// );
42///
43/// assert_eq!(
44/// schema
45/// .execute("{ value2 }")
46/// .await
47/// .into_result()
48/// .unwrap()
49/// .cache_control,
50/// CacheControl {
51/// public: false,
52/// max_age: 60
53/// }
54/// );
55///
56/// assert_eq!(
57/// schema
58/// .execute("{ value1 value2 }")
59/// .await
60/// .into_result()
61/// .unwrap()
62/// .cache_control,
63/// CacheControl {
64/// public: false,
65/// max_age: 30
66/// }
67/// );
68///
69/// assert_eq!(
70/// schema
71/// .execute("{ value1 value2 value3 }")
72/// .await
73/// .into_result()
74/// .unwrap()
75/// .cache_control,
76/// CacheControl {
77/// public: false,
78/// max_age: -1
79/// }
80/// );
81/// # });
82/// ```
83#[derive(Clone, Copy, PartialEq, Eq, Debug)]
84pub struct CacheControl {
85 /// Scope is public, default is true.
86 pub public: bool,
87
88 /// Cache max age, `-1` represent `no-cache`, default is 0.
89 pub max_age: i32,
90}
91
92impl Default for CacheControl {
93 fn default() -> Self {
94 Self {
95 public: true,
96 max_age: 0,
97 }
98 }
99}
100
101impl CacheControl {
102 /// Get 'Cache-Control' header value.
103 #[must_use]
104 pub fn value(&self) -> Option<String> {
105 let mut value = if self.max_age > 0 {
106 format!("max-age={}", self.max_age)
107 } else if self.max_age == -1 {
108 "no-cache".to_string()
109 } else {
110 String::new()
111 };
112
113 if !self.public {
114 if !value.is_empty() {
115 value += ", ";
116 }
117 value += "private";
118 }
119
120 if !value.is_empty() { Some(value) } else { None }
121 }
122}
123
124impl CacheControl {
125 #[must_use]
126 pub(crate) fn merge(self, other: &CacheControl) -> CacheControl {
127 CacheControl {
128 public: self.public && other.public,
129 max_age: match (self.max_age, other.max_age) {
130 (-1, _) => -1,
131 (_, -1) => -1,
132 (a, 0) => a,
133 (0, b) => b,
134 (a, b) => a.min(b),
135 },
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn to_value() {
146 assert_eq!(
147 CacheControl {
148 public: true,
149 max_age: 0,
150 }
151 .value(),
152 None
153 );
154
155 assert_eq!(
156 CacheControl {
157 public: false,
158 max_age: 0,
159 }
160 .value(),
161 Some("private".to_string())
162 );
163
164 assert_eq!(
165 CacheControl {
166 public: false,
167 max_age: 10,
168 }
169 .value(),
170 Some("max-age=10, private".to_string())
171 );
172
173 assert_eq!(
174 CacheControl {
175 public: true,
176 max_age: 10,
177 }
178 .value(),
179 Some("max-age=10".to_string())
180 );
181
182 assert_eq!(
183 CacheControl {
184 public: true,
185 max_age: -1,
186 }
187 .value(),
188 Some("no-cache".to_string())
189 );
190
191 assert_eq!(
192 CacheControl {
193 public: false,
194 max_age: -1,
195 }
196 .value(),
197 Some("no-cache, private".to_string())
198 );
199 }
200}