From c9001a32f57d2481141ab61e5c64da0be49a5db3 Mon Sep 17 00:00:00 2001 From: Rost Date: Wed, 28 Jun 2023 20:23:39 +0200 Subject: [PATCH 1/5] Fix string value in enum --- apollo-gateway-rs/src/validation/utils.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apollo-gateway-rs/src/validation/utils.rs b/apollo-gateway-rs/src/validation/utils.rs index e80e3c1..4ef183d 100644 --- a/apollo-gateway-rs/src/validation/utils.rs +++ b/apollo-gateway-rs/src/validation/utils.rs @@ -3,7 +3,7 @@ use std::fmt::{Display, Formatter, Result as FmtResult}; use crate::schema::{ComposedSchema, TypeKind}; use parser::types::{BaseType, Type}; -use value::ConstValue; +use value::{ConstValue, Name}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Scope<'a> { @@ -117,6 +117,18 @@ pub fn is_valid_input_value( } else { None } + } else if let ConstValue::String(v) = value { + if ty.enum_values.contains_key(&Name::new(v.to_string())) { + None + } else { + Some(valid_error( + &path_node, + format!( + "enumeration type \"{}\" does not contain the value \"{}\"", + ty.name, value + ) + )) + } } else { Some(valid_error( &path_node, From 1cece176502bebd6c5f7c34754118d6ebab11475 Mon Sep 17 00:00:00 2001 From: Rost Date: Wed, 28 Jun 2023 20:25:33 +0200 Subject: [PATCH 2/5] cargo lock --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index fe78ee8..9d13c04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -392,7 +392,7 @@ checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" [[package]] name = "apollo-gateway-rs" -version = "0.8.0" +version = "0.8.1" dependencies = [ "actix", "actix-web", From 4e68536395ff38a92c8ee3bd3de5c61ee828f37e Mon Sep 17 00:00:00 2001 From: Rost Date: Wed, 28 Jun 2023 20:23:39 +0200 Subject: [PATCH 3/5] Fix string value in enum --- apollo-gateway-rs/src/validation/utils.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apollo-gateway-rs/src/validation/utils.rs b/apollo-gateway-rs/src/validation/utils.rs index e80e3c1..4ef183d 100644 --- a/apollo-gateway-rs/src/validation/utils.rs +++ b/apollo-gateway-rs/src/validation/utils.rs @@ -3,7 +3,7 @@ use std::fmt::{Display, Formatter, Result as FmtResult}; use crate::schema::{ComposedSchema, TypeKind}; use parser::types::{BaseType, Type}; -use value::ConstValue; +use value::{ConstValue, Name}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Scope<'a> { @@ -117,6 +117,18 @@ pub fn is_valid_input_value( } else { None } + } else if let ConstValue::String(v) = value { + if ty.enum_values.contains_key(&Name::new(v.to_string())) { + None + } else { + Some(valid_error( + &path_node, + format!( + "enumeration type \"{}\" does not contain the value \"{}\"", + ty.name, value + ) + )) + } } else { Some(valid_error( &path_node, From 1a8142fb502ea376a1e15158345b1f7bee6fe05e Mon Sep 17 00:00:00 2001 From: Rost Date: Sat, 8 Jul 2023 14:21:19 +0200 Subject: [PATCH 4/5] data to Option type --- Cargo.lock | 2 +- apollo-gateway-rs/src/handler/executor.rs | 21 ++++++++++++------- .../src/handler/shared_route_table.rs | 7 +++---- .../src/handler/websocket/subscription.rs | 3 +-- apollo-gateway-rs/src/planner/builder.rs | 2 +- apollo-gateway-rs/src/planner/response.rs | 3 ++- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb163f2..7ac1cd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -408,7 +408,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "apollo-gateway-rs" -version = "0.8.2" +version = "0.8.3" dependencies = [ "actix", "actix-web", diff --git a/apollo-gateway-rs/src/handler/executor.rs b/apollo-gateway-rs/src/handler/executor.rs index f5a0402..a13ffd3 100644 --- a/apollo-gateway-rs/src/handler/executor.rs +++ b/apollo-gateway-rs/src/handler/executor.rs @@ -42,7 +42,7 @@ impl<'e> Executor<'e> { self.resp.into_inner() } RootNode::Subscribe(_) => Response { - data: ConstValue::Null, + data: None, errors: vec![ServerError { message: "Not supported".to_string(), path: Default::default(), @@ -100,7 +100,7 @@ impl<'e> Executor<'e> { id, node.service, RequestData::new(node.query.to_string()) - .variables(node.variables.to_variables()), + .variables(node.variables.to_variables()), tx.clone(), ) .with_context(cx)) @@ -113,7 +113,7 @@ impl<'e> Executor<'e> { vec![KEY_ERROR.string(err.to_string())], ); Response { - data: ConstValue::Null, + data: None, errors: vec![ServerError { message: err.to_string(), path: Default::default(), @@ -193,7 +193,12 @@ impl<'e> Executor<'e> { async fn execute_introspection_node(&self, introspection: &IntrospectionNode) { let value = IntrospectionRoot.resolve(&introspection.selection_set, self.schema); let mut current_resp = self.resp.lock().await; - merge_data(&mut current_resp.data, value); + if current_resp.data .is_none() { + current_resp.data = Some(ConstValue::Null) + } + if let Some(data) = &mut current_resp.data { + merge_data(data, value); + } } async fn execute_fetch_node(&self, fetcher: &impl Fetcher, fetch: &FetchNode<'_>) { @@ -231,7 +236,7 @@ impl<'e> Executor<'e> { if resp.errors.is_empty() { add_tracing_spans(&mut resp); current_resp.headers = resp.headers; - merge_data(&mut current_resp.data, resp.data); + merge_data(current_resp.data.as_mut().unwrap_or(&mut ConstValue::Null), resp.data.unwrap_or_default()); } else { rewrite_errors(None, &mut current_resp.errors, resp.errors); } @@ -407,7 +412,7 @@ impl<'e> Executor<'e> { let mut resp = self.resp.lock().await; get_representations( &mut representations, - &mut resp.data, + resp.data.as_mut().unwrap_or(&mut ConstValue::Null), &flatten.path, flatten.prefix, ); @@ -467,10 +472,10 @@ impl<'e> Executor<'e> { Ok(mut resp) => { if resp.errors.is_empty() { add_tracing_spans(&mut resp); - if let ConstValue::Object(mut data) = resp.data { + if let ConstValue::Object(mut data) = resp.data.unwrap_or_default() { if let Some(ConstValue::List(values)) = data.remove("_entities") { flatten_values( - &mut current_resp.data, + current_resp.data.as_mut().unwrap_or(&mut ConstValue::Null), &flatten.path, &mut values.into_iter().fuse(), &mut flags.into_iter().fuse(), diff --git a/apollo-gateway-rs/src/handler/shared_route_table.rs b/apollo-gateway-rs/src/handler/shared_route_table.rs index 75790e3..e07d6ac 100644 --- a/apollo-gateway-rs/src/handler/shared_route_table.rs +++ b/apollo-gateway-rs/src/handler/shared_route_table.rs @@ -11,7 +11,6 @@ use parser::types::{ExecutableDocument, Selection, SelectionSet}; use serde::Deserialize; use tokio::sync::{mpsc, RwLock}; use tokio::time::{Duration, Instant}; -use value::ConstValue; use crate::datasource::RemoteGraphQLDataSource; use crate::GraphqlSourceMiddleware; @@ -116,7 +115,7 @@ impl SharedRouteTable { .await .with_context(|| format!("Failed to fetch SDL from '{}'.", service))?; let resp: ResponseQuery = - value::from_value(resp.data).context("Failed to parse response.")?; + value::from_value(resp.data.unwrap_or_default()).context("Failed to parse response.")?; let document = parser::parse_schema(resp.service.sdl) .with_context(|| format!("Invalid SDL from '{}'.", service))?; Ok::<_, Error>((service.to_string(), document)) @@ -156,7 +155,7 @@ impl SharedRouteTable { Ok(_) => {}, Err(e) => { let response = Response { - data: ConstValue::Null, + data: None, errors: vec![e], extensions: Default::default(), headers: Default::default(), @@ -175,7 +174,7 @@ impl SharedRouteTable { Some((composed_schema, route_table)) => (composed_schema, route_table), _ => { let response = Response { - data: ConstValue::Null, + data: None, errors: vec![ServerError::new("Not ready.")], extensions: Default::default(), headers: Default::default(), diff --git a/apollo-gateway-rs/src/handler/websocket/subscription.rs b/apollo-gateway-rs/src/handler/websocket/subscription.rs index b66765f..566aacb 100644 --- a/apollo-gateway-rs/src/handler/websocket/subscription.rs +++ b/apollo-gateway-rs/src/handler/websocket/subscription.rs @@ -4,7 +4,6 @@ use actix::{Actor, AsyncContext, ActorContext, Handler, StreamHandler}; use crate::schema::ComposedSchema; use actix_web_actors::ws; use actix_web_actors::ws::{CloseCode, CloseReason, Message, ProtocolError}; -use value::ConstValue; use crate::planner::{Response, ServerError}; use crate::{RemoteGraphQLDataSource, Context, ServiceRouteTable, GraphqlSourceMiddleware}; use super::protocol::{ClientMessage, ConnectionError, ServerMessage}; @@ -93,7 +92,7 @@ impl StreamHandler document, Err(err) => { let resp = Response { - data: ConstValue::Null, + data: None, errors: vec![ServerError::new(err.to_string())], extensions: Default::default(), headers: Default::default() diff --git a/apollo-gateway-rs/src/planner/builder.rs b/apollo-gateway-rs/src/planner/builder.rs index a03301d..2bbe49e 100644 --- a/apollo-gateway-rs/src/planner/builder.rs +++ b/apollo-gateway-rs/src/planner/builder.rs @@ -62,7 +62,7 @@ impl<'a> PlanBuilder<'a> { crate::validation::check_rules(self.schema, &self.document, &self.variables); if !rule_errors.is_empty() { return Err(Response { - data: ConstValue::Null, + data: None, errors: rule_errors .into_iter() .map(|err| ServerError { diff --git a/apollo-gateway-rs/src/planner/response.rs b/apollo-gateway-rs/src/planner/response.rs index 7435472..674983f 100644 --- a/apollo-gateway-rs/src/planner/response.rs +++ b/apollo-gateway-rs/src/planner/response.rs @@ -38,7 +38,8 @@ impl ServerError { #[derive(Debug, Serialize, Deserialize, Default)] pub struct Response { - pub data: ConstValue, + #[serde(skip_serializing_if = "Option::is_none", default)] + pub data: Option, #[serde(skip_serializing_if = "Vec::is_empty", default)] pub errors: Vec, From b289b9ad2a799195639396ce0e81eba21c534624 Mon Sep 17 00:00:00 2001 From: Rost Date: Sun, 9 Jul 2023 23:55:19 +0200 Subject: [PATCH 5/5] fix: execute_fetch_node --- apollo-gateway-rs/src/handler/executor.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apollo-gateway-rs/src/handler/executor.rs b/apollo-gateway-rs/src/handler/executor.rs index a13ffd3..f6e0848 100644 --- a/apollo-gateway-rs/src/handler/executor.rs +++ b/apollo-gateway-rs/src/handler/executor.rs @@ -236,7 +236,12 @@ impl<'e> Executor<'e> { if resp.errors.is_empty() { add_tracing_spans(&mut resp); current_resp.headers = resp.headers; - merge_data(current_resp.data.as_mut().unwrap_or(&mut ConstValue::Null), resp.data.unwrap_or_default()); + if current_resp.data .is_none() { + current_resp.data = Some(ConstValue::Null) + } + if let Some(data) = &mut current_resp.data { + merge_data(data, resp.data.unwrap_or(ConstValue::Null)); + } } else { rewrite_errors(None, &mut current_resp.errors, resp.errors); }