diff --git a/apollo-router-core/src/query_planner/mod.rs b/apollo-router-core/src/query_planner/mod.rs index a7d6eaa040..79cfe7633c 100644 --- a/apollo-router-core/src/query_planner/mod.rs +++ b/apollo-router-core/src/query_planner/mod.rs @@ -241,9 +241,9 @@ impl PlanNode { let required = self.variable_usage().collect::>(); let provided = request .variables - .as_ref() - .map(|v| v.keys().map(|x| x.as_str()).collect::>()) - .unwrap_or_default(); + .keys() + .map(|x| x.as_str()) + .collect::>(); required .difference(&provided) .map(|x| FetchError::ValidationMissingVariable { @@ -295,11 +295,10 @@ impl FetchNode { let mut variables = Object::with_capacity(1 + variable_usages.len()); variables.extend(variable_usages.iter().filter_map(|key| { - request.variables.as_ref().map(|v| { - v.get(key) - .map(|value| (key.clone(), value.clone())) - .unwrap_or_default() - }) + request + .variables + .get(key) + .map(|value| (key.clone(), value.clone())) })); { @@ -318,7 +317,7 @@ impl FetchNode { .stream( Request::builder() .query(operation) - .variables(Some(Arc::new(variables))) + .variables(Arc::new(variables)) .build(), ) .await @@ -390,9 +389,8 @@ impl FetchNode { .filter_map(|key| { request .variables - .as_ref() - .map(|v| v.get(key).map(|value| (key.clone(), value.clone()))) - .unwrap_or_default() + .get(key) + .map(|value| (key.clone(), value.clone())) }) .collect::(), ); diff --git a/apollo-router-core/src/request.rs b/apollo-router-core/src/request.rs index 51952a446a..5778794ed5 100644 --- a/apollo-router-core/src/request.rs +++ b/apollo-router-core/src/request.rs @@ -20,9 +20,13 @@ pub struct Request { pub operation_name: Option, /// The optional variables in the form of a json object. - #[serde(skip_serializing_if = "Option::is_none", default)] + #[serde( + skip_serializing_if = "Object::is_empty", + default, + deserialize_with = "deserialize_null_default" + )] #[builder(default)] - pub variables: Option>, + pub variables: Arc, /// extensions. #[serde(skip_serializing_if = "Object::is_empty", default)] @@ -30,6 +34,16 @@ pub struct Request { pub extensions: Object, } +// NOTE: this deserialize helper is used to transform `null` to Default::default() +fn deserialize_null_default<'de, D, T: Default + Deserialize<'de>>( + deserializer: D, +) -> Result +where + D: serde::Deserializer<'de>, +{ + >::deserialize(deserializer).map(|x| x.unwrap_or_default()) +} + #[cfg(test)] mod tests { use super::*;