Expected Behavior
When using cloudevents.http.from_http(headers, body), an event that is missing any of the required fields should result in a cloud_exceptions.MissingRequiredFields exception with a message that indicates which field is missing.
Actual Behavior
When given a Binary Cloud Event that is missing a required field ce-id, ce-source, or ce-type, it will return a MissingRequiredFields error with the incorrect error message Failed to find specversion in HTTP request.
Steps to Reproduce the Problem
from cloudevents.http import from_http
from cloudevents.exceptions import MissingRequiredFields
# Correctly does not result in an error if all required fields are present
def test_from_http():
event = from_http({"ce-specversion": "1.0", "ce-id":"123", "ce-type": "test-type", "ce-source": "test-source"}, "{}")
assert event["id"] == "123"
# Returns an incorrect error message
def test_from_http_missing_id_binary():
try:
event = from_http({"ce-specversion": "1.0", "ce-type": "test-type", "ce-source": "test-source"}, "{}")
assert 1 == 2
except MissingRequiredFields as e:
assert "Failed to find specversion in HTTP request" == str(e)
# Returns the appropriate message
def test_from_http_missing_id_structured():
try:
event = from_http({}, "{\"specversion\": \"1.0\", \"type\": \"test-type\", \"source\": \"test-source\"}")
assert 1 == 2
except MissingRequiredFields as e:
assert "Missing required attributes: {'id'}" == str(e)
The code flow is as follows:
- it checks
is_binary(headers)
- It calls
binary_parser.can_read
|
def is_binary(headers: typing.Dict[str, str]) -> bool: |
|
"""Uses internal marshallers to determine whether this event is binary |
|
:param headers: the HTTP headers |
|
:type headers: typing.Dict[str, str] |
|
:returns bool: returns a bool indicating whether the headers indicate |
|
a binary event type |
|
""" |
|
headers = {key.lower(): value for key, value in headers.items()} |
|
content_type = headers.get("content-type", "") |
|
binary_parser = binary.BinaryHTTPCloudEventConverter() |
|
return binary_parser.can_read(content_type=content_type, headers=headers) |
- it calls
has_binary_headers
|
def can_read( |
|
self, |
|
content_type: str = None, |
|
headers: typing.Dict[str, str] = {"ce-specversion": None}, |
|
) -> bool: |
|
|
|
return has_binary_headers(headers) |
has_binary_headers checks for the presence of all required fields, which in this test case is false because it is missing ce-id
|
def has_binary_headers(headers: typing.Dict[str, str]) -> bool: |
|
return ( |
|
"ce-specversion" in headers |
|
and "ce-source" in headers |
|
and "ce-type" in headers |
|
and "ce-id" in headers |
|
) |
- it then falls through and tries to get the specversion here
|
specversion = raw_ce.get("specversion", None) |
- specversion is never set and the error gets thrown here
|
if specversion is None: |
|
raise cloud_exceptions.MissingRequiredFields( |
|
"Failed to find specversion in HTTP request" |
|
) |
I think that the solution might be as simple as changing all of the ands to ors in the has_binary_headers method in step 4.
Specifications
- Platform: Mac OS
- Python Version: 3.9.4
Expected Behavior
When using
cloudevents.http.from_http(headers, body), an event that is missing any of the required fields should result in acloud_exceptions.MissingRequiredFieldsexception with a message that indicates which field is missing.Actual Behavior
When given a Binary Cloud Event that is missing a required field
ce-id,ce-source, orce-type, it will return aMissingRequiredFieldserror with the incorrect error messageFailed to find specversion in HTTP request.Steps to Reproduce the Problem
The code flow is as follows:
is_binary(headers)sdk-python/cloudevents/http/http_methods.py
Line 46 in b83bfc5
binary_parser.can_readsdk-python/cloudevents/http/event_type.py
Lines 6 to 16 in b83bfc5
has_binary_headerssdk-python/cloudevents/sdk/converters/binary.py
Lines 29 to 35 in b83bfc5
has_binary_headerschecks for the presence of all required fields, which in this test case is false because it is missingce-idsdk-python/cloudevents/sdk/converters/util.py
Lines 4 to 10 in b83bfc5
sdk-python/cloudevents/http/http_methods.py
Line 57 in b83bfc5
sdk-python/cloudevents/http/http_methods.py
Lines 64 to 67 in b83bfc5
I think that the solution might be as simple as changing all of the
ands toors in thehas_binary_headersmethod in step 4.Specifications