From ae68c6995f8c78c2c629a0082e3cbbedce2d0e5d Mon Sep 17 00:00:00 2001 From: Jim Crossley Date: Tue, 9 Nov 2021 22:47:56 -0500 Subject: [PATCH] Don't fail to deserialize data_base64 even if datacontenttype lies This fixes #160 From the spec: "When a CloudEvent is deserialized from JSON, the presence of the data_base64 member clearly indicates that the value is a Base64 encoded binary data, which the deserializer MUST decode into a binary runtime data type. The deserializer MAY further interpret this binary data according to the datacontenttype." https://github.com/cloudevents/spec/blob/master/cloudevents/formats/json-format.md#312-payload-deserialization Signed-off-by: Jim Crossley --- src/event/builder.rs | 4 ++++ src/event/v10/format.rs | 8 +++++++- src/test/fixtures/v10.rs | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/event/builder.rs b/src/event/builder.rs index d826242..ce65dea 100644 --- a/src/event/builder.rs +++ b/src/event/builder.rs @@ -200,6 +200,10 @@ mod tests { fixtures::v10::full_json_base64_data_json(), fixtures::v10::full_json_data() ), + case::full_v10_with_non_json_base64_data( + fixtures::v10::full_non_json_base64_data(), + fixtures::v10::full_non_json_data() + ), case::full_v10_with_xml_string_data( fixtures::v10::full_xml_string_data_json(), fixtures::v10::full_xml_string_data() diff --git a/src/event/v10/format.rs b/src/event/v10/format.rs index 50f1e36..ed39d91 100644 --- a/src/event/v10/format.rs +++ b/src/event/v10/format.rs @@ -42,7 +42,13 @@ impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer { Ok(match (data, data_base64, is_json) { (Some(d), None, true) => Some(Data::Json(parse_data_json!(d, E)?)), (Some(d), None, false) => Some(Data::String(parse_data_string!(d, E)?)), - (None, Some(d), true) => Some(Data::Json(parse_json_data_base64!(d, E)?)), + (None, Some(d), true) => { + let dc = d.to_owned(); + match parse_json_data_base64!(dc, E) { + Ok(x) => Some(Data::Json(x)), + Err(_) => Some(Data::Binary(parse_data_base64!(d, E)?)), + } + } (None, Some(d), false) => Some(Data::Binary(parse_data_base64!(d, E)?)), (Some(_), Some(_), _) => { return Err(E::custom("Cannot have both data and data_base64 field")) diff --git a/src/test/fixtures/v10.rs b/src/test/fixtures/v10.rs index 864f4b1..0a8431f 100644 --- a/src/test/fixtures/v10.rs +++ b/src/test/fixtures/v10.rs @@ -170,6 +170,28 @@ pub fn full_json_base64_data_json() -> Value { }) } +pub fn full_non_json_base64_data() -> Value { + match full_json_base64_data_json() { + Value::Object(mut m) => { + m.insert( + "data_base64".to_string(), + Value::String(base64::encode(b"hello world")), + ); + Value::Object(m) + } + _ => Value::Null, + } +} + +pub fn full_non_json_data() -> Event { + let mut event = full_json_data(); + let value = full_non_json_base64_data(); + if let Value::Object(m) = value { + event.set_data_unchecked(base64::decode(m["data_base64"].as_str().unwrap()).unwrap()); + } + event +} + pub fn full_xml_string_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension();