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() {
121 Some(value)
122 } else {
123 None
124 }
125 }
126}
127
128impl CacheControl {
129 #[must_use]
130 pub(crate) fn merge(self, other: &CacheControl) -> CacheControl {
131 CacheControl {
132 public: self.public && other.public,
133 max_age: match (self.max_age, other.max_age) {
134 (-1, _) => -1,
135 (_, -1) => -1,
136 (a, 0) => a,
137 (0, b) => b,
138 (a, b) => a.min(b),
139 },
140 }
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn to_value() {
150 assert_eq!(
151 CacheControl {
152 public: true,
153 max_age: 0,
154 }
155 .value(),
156 None
157 );
158
159 assert_eq!(
160 CacheControl {
161 public: false,
162 max_age: 0,
163 }
164 .value(),
165 Some("private".to_string())
166 );
167
168 assert_eq!(
169 CacheControl {
170 public: false,
171 max_age: 10,
172 }
173 .value(),
174 Some("max-age=10, private".to_string())
175 );
176
177 assert_eq!(
178 CacheControl {
179 public: true,
180 max_age: 10,
181 }
182 .value(),
183 Some("max-age=10".to_string())
184 );
185
186 assert_eq!(
187 CacheControl {
188 public: true,
189 max_age: -1,
190 }
191 .value(),
192 Some("no-cache".to_string())
193 );
194
195 assert_eq!(
196 CacheControl {
197 public: false,
198 max_age: -1,
199 }
200 .value(),
201 Some("no-cache, private".to_string())
202 );
203 }
204}