diff --git a/apollo-federation/src/sources/connect/expand/mod.rs b/apollo-federation/src/sources/connect/expand/mod.rs index 22e7d4aa36..95b5327059 100644 --- a/apollo-federation/src/sources/connect/expand/mod.rs +++ b/apollo-federation/src/sources/connect/expand/mod.rs @@ -771,7 +771,7 @@ mod helpers { // (externally-provided) variables like $this, $args, and // $config. The $ and @ variables, by contrast, are always bound // to something within the input data. - KnownVariable::Dollar | KnownVariable::AtSign => { + KnownVariable::Dollar | KnownVariable::AtSign | KnownVariable::Status => { return None; } }; diff --git a/apollo-federation/src/sources/connect/json_selection/known_var.rs b/apollo-federation/src/sources/connect/json_selection/known_var.rs index 441a13cae1..84b0194a55 100644 --- a/apollo-federation/src/sources/connect/json_selection/known_var.rs +++ b/apollo-federation/src/sources/connect/json_selection/known_var.rs @@ -6,6 +6,7 @@ pub(crate) enum KnownVariable { This, Args, Config, + Status, Dollar, AtSign, } @@ -16,6 +17,7 @@ impl KnownVariable { "$this" => Some(Self::This), "$args" => Some(Self::Args), "$config" => Some(Self::Config), + "$status" => Some(Self::Status), "$" => Some(Self::Dollar), "@" => Some(Self::AtSign), _ => None, @@ -27,6 +29,7 @@ impl KnownVariable { Self::This => "$this", Self::Args => "$args", Self::Config => "$config", + Self::Status => "$status", Self::Dollar => "$", Self::AtSign => "@", } diff --git a/apollo-router/src/plugins/connectors/handle_responses.rs b/apollo-router/src/plugins/connectors/handle_responses.rs index 8a12a66ca5..4810b17f34 100644 --- a/apollo-router/src/plugins/connectors/handle_responses.rs +++ b/apollo-router/src/plugins/connectors/handle_responses.rs @@ -82,7 +82,11 @@ pub(crate) async fn handle_responses( let mut res_data = { let (res, apply_to_errors) = response_key.selection().apply_with_vars( &json_data, - &response_key.inputs().merge(connector.config.as_ref(), None), + &response_key.inputs().merge( + connector.config.as_ref(), + None, + Some(parts.status.as_u16()), + ), ); if let Some(ref debug) = debug { @@ -748,4 +752,77 @@ mod tests { } "###); } + + #[tokio::test] + async fn test_handle_responses_status() { + let connector = Connector { + id: ConnectId::new( + "subgraph_name".into(), + None, + name!(Query), + name!(hello), + 0, + "test label", + ), + transport: HttpJsonTransport { + source_url: Some(Url::parse("http://localhost/api").unwrap()), + connect_template: "/path".parse().unwrap(), + method: HTTPMethod::Get, + headers: Default::default(), + body: Default::default(), + }, + selection: JSONSelection::parse("$status").unwrap(), + entity_resolver: None, + config: Default::default(), + max_requests: None, + }; + + let response1: http::Response = http::Response::builder() + .status(201) + .body(hyper::Body::from(r#"{}"#).into()) + .expect("response builder"); + let response_key1 = ResponseKey::RootField { + name: "hello".to_string(), + inputs: Default::default(), + typename: ResponseTypeName::Concrete("Int".to_string()), + selection: Arc::new(JSONSelection::parse("$status").unwrap()), + }; + + let res = super::handle_responses( + vec![ConnectorResponse { + result: response1.into(), + key: response_key1, + debug_request: None, + }], + &connector, + &None, + ) + .await + .unwrap(); + + assert_debug_snapshot!(res, @r###" + Response { + response: Response { + status: 200, + version: HTTP/1.1, + headers: {}, + body: Response { + label: None, + data: Some( + Object({ + "hello": Number(201), + }), + ), + path: None, + errors: [], + extensions: {}, + has_next: None, + subscribed: None, + created_at: None, + incremental: [], + }, + }, + } + "###); + } } diff --git a/apollo-router/src/plugins/connectors/make_requests.rs b/apollo-router/src/plugins/connectors/make_requests.rs index 9ff545cd1e..4f8fa8f443 100644 --- a/apollo-router/src/plugins/connectors/make_requests.rs +++ b/apollo-router/src/plugins/connectors/make_requests.rs @@ -33,6 +33,7 @@ impl RequestInputs { &self, config: Option<&CustomConfiguration>, context: Option>, + status: Option, ) -> IndexMap { let mut map = IndexMap::with_capacity_and_hasher(3, Default::default()); map.insert("$args".to_string(), Value::Object(self.args.clone())); @@ -43,6 +44,9 @@ impl RequestInputs { if let Some(config) = config { map.insert("$config".to_string(), json!(config)); } + if let Some(status) = status { + map.insert("$status".to_string(), Value::Number(status.into())); + } map } } @@ -127,7 +131,7 @@ fn request_params_to_requests( &connector.transport, response_key .inputs() - .merge(connector.config.as_ref(), Some(context.clone())), + .merge(connector.config.as_ref(), Some(context.clone()), None), original_request, debug, )?;