Skip to content

Commit d235ef3

Browse files
committed
Fix to_binary crash on missing datacontenttype or non-string attrs
The Kafka binary conversion to_binary() read the optional datacontenttype attribute with event["datacontenttype"], raising KeyError for any event that does not set it (datacontenttype is optional in the CloudEvents spec). It also called .encode() directly on attribute values, raising AttributeError for spec-legal non-string extension attributes (e.g. integers). Read datacontenttype via .get() -- matching the sibling to_structured(), which already guards this attribute -- and stringify attribute values before encoding, matching the newer core Kafka binding. Add regression tests for both cases. Signed-off-by: Md. Amdadul Bari Imad <amdadulbari@gmail.com>
1 parent 24842fd commit d235ef3

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

src/cloudevents/v1/kafka/conversion.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,13 @@ def to_binary(
9292
)
9393

9494
headers = {}
95-
if event["datacontenttype"]:
96-
headers["content-type"] = event["datacontenttype"].encode("utf-8")
95+
datacontenttype = event.get("datacontenttype")
96+
if datacontenttype:
97+
headers["content-type"] = datacontenttype.encode("utf-8")
9798
for attr, value in event.get_attributes().items():
9899
if attr not in ["data", "partitionkey", "datacontenttype"]:
99100
if value is not None:
100-
headers["ce_{0}".format(attr)] = value.encode("utf-8")
101+
headers["ce_{0}".format(attr)] = str(value).encode("utf-8")
101102

102103
try:
103104
data = data_marshaller(event.get_data())

tests/test_v1_compat/test_kafka_conversions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ def test_sets_headers(self, source_event):
129129
assert "data" not in result.headers
130130
assert "partitionkey" not in result.headers
131131

132+
def test_no_datacontenttype(self, source_event):
133+
# datacontenttype is optional; to_binary must not raise KeyError when it
134+
# is absent, and should simply omit the content-type header.
135+
del source_event["datacontenttype"]
136+
result = to_binary(source_event)
137+
assert "content-type" not in result.headers
138+
139+
def test_non_string_extension_attribute(self, source_event):
140+
# Extension attributes may be non-string (e.g. int) per the CloudEvents
141+
# spec; to_binary must stringify them rather than raising AttributeError.
142+
source_event["extension1"] = 5
143+
result = to_binary(source_event)
144+
assert result.headers["ce_extension1"] == b"5"
145+
132146
def test_raise_marshaller_exception(self, source_event):
133147
with pytest.raises(cloud_exceptions.DataMarshallerError):
134148
to_binary(source_event, data_marshaller=failing_func)

0 commit comments

Comments
 (0)