diff --git a/derive/src/args.rs b/derive/src/args.rs index 5be1c4c4..5d987078 100644 --- a/derive/src/args.rs +++ b/derive/src/args.rs @@ -17,6 +17,7 @@ use crate::validators::Validators; pub struct CacheControl { public: bool, private: bool, + pub no_cache: bool, pub max_age: usize, } @@ -25,6 +26,7 @@ impl Default for CacheControl { Self { public: true, private: false, + no_cache: false, max_age: 0, } } diff --git a/derive/src/complex_object.rs b/derive/src/complex_object.rs index 51256b42..abd78700 100644 --- a/derive/src/complex_object.rs +++ b/derive/src/complex_object.rs @@ -189,7 +189,11 @@ pub fn generate( }; let cache_control = { let public = method_args.cache_control.is_public(); - let max_age = method_args.cache_control.max_age; + let max_age = if method_args.cache_control.no_cache { + -1 + } else { + method_args.cache_control.max_age as i32 + }; quote! { #crate_name::CacheControl { public: #public, diff --git a/derive/src/object.rs b/derive/src/object.rs index 6f921d0d..08566819 100644 --- a/derive/src/object.rs +++ b/derive/src/object.rs @@ -335,7 +335,11 @@ pub fn generate( }; let cache_control = { let public = method_args.cache_control.is_public(); - let max_age = method_args.cache_control.max_age; + let max_age = if method_args.cache_control.no_cache { + -1 + } else { + method_args.cache_control.max_age as i32 + }; quote! { #crate_name::CacheControl { public: #public, @@ -583,7 +587,11 @@ pub fn generate( let cache_control = { let public = object_args.cache_control.is_public(); - let max_age = object_args.cache_control.max_age; + let max_age = if object_args.cache_control.no_cache { + -1 + } else { + object_args.cache_control.max_age as i32 + }; quote! { #crate_name::CacheControl { public: #public, diff --git a/derive/src/simple_object.rs b/derive/src/simple_object.rs index 1949913c..49d74df5 100644 --- a/derive/src/simple_object.rs +++ b/derive/src/simple_object.rs @@ -161,7 +161,11 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult GeneratorResult i32 { /// 0 /// } +/// +/// #[graphql(cache_control(no_cache))] +/// async fn value3(&self) -> i32 { +/// 0 +/// } /// } /// /// # tokio::runtime::Runtime::new().unwrap().block_on(async { @@ -34,6 +39,7 @@ /// max_age: 30 /// } /// ); +/// /// assert_eq!( /// schema /// .execute("{ value2 }") @@ -46,6 +52,7 @@ /// max_age: 60 /// } /// ); +/// /// assert_eq!( /// schema /// .execute("{ value1 value2 }") @@ -58,6 +65,19 @@ /// max_age: 30 /// } /// ); +/// +/// assert_eq!( +/// schema +/// .execute("{ value1 value2 value3 }") +/// .await +/// .into_result() +/// .unwrap() +/// .cache_control, +/// CacheControl { +/// public: false, +/// max_age: -1 +/// } +/// ); /// # }); /// ``` #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -65,8 +85,8 @@ pub struct CacheControl { /// Scope is public, default is true. pub public: bool, - /// Cache max age, default is 0. - pub max_age: usize, + /// Cache max age, `-1` represent `no-cache`, default is 0. + pub max_age: i32, } impl Default for CacheControl { @@ -82,12 +102,23 @@ impl CacheControl { /// Get 'Cache-Control' header value. #[must_use] pub fn value(&self) -> Option { - if self.max_age > 0 { - Some(format!( - "max-age={}{}", - self.max_age, - if self.public { "" } else { ", private" } - )) + let mut value = if self.max_age > 0 { + format!("max-age={}", self.max_age) + } else if self.max_age == -1 { + "no-cache".to_string() + } else { + String::new() + }; + + if !self.public { + if !value.is_empty() { + value += ", "; + } + value += "private"; + } + + if !value.is_empty() { + Some(value) } else { None } @@ -99,13 +130,75 @@ impl CacheControl { pub(crate) fn merge(self, other: &CacheControl) -> CacheControl { CacheControl { public: self.public && other.public, - max_age: if self.max_age == 0 { - other.max_age - } else if other.max_age == 0 { - self.max_age - } else { - self.max_age.min(other.max_age) + max_age: match (self.max_age, other.max_age) { + (-1, _) => -1, + (_, -1) => -1, + (a, 0) => a, + (0, b) => b, + (a, b) => a.min(b), }, } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn to_value() { + assert_eq!( + CacheControl { + public: true, + max_age: 0, + } + .value(), + None + ); + + assert_eq!( + CacheControl { + public: false, + max_age: 0, + } + .value(), + Some("private".to_string()) + ); + + assert_eq!( + CacheControl { + public: false, + max_age: 10, + } + .value(), + Some("max-age=10, private".to_string()) + ); + + assert_eq!( + CacheControl { + public: true, + max_age: 10, + } + .value(), + Some("max-age=10".to_string()) + ); + + assert_eq!( + CacheControl { + public: true, + max_age: -1, + } + .value(), + Some("no-cache".to_string()) + ); + + assert_eq!( + CacheControl { + public: false, + max_age: -1, + } + .value(), + Some("no-cache, private".to_string()) + ); + } +}