Repository: GoogleCloudPlatform/functions-framework-python
Pull request #187 (2022-05-07 05:24:02)

fix: for issue #170 gracefully handle pubsub messages without attributes in them
fix: for issue #170 gracefully handle pubsub messages without attributes in them


anniefu: Hi @MikeMoore63, thanks for the contribution! Would you mind taking a pass at fixing the failing unit test? 
MikeMoore63: Any progress on this now tests have passed?
anniefu: Thanks for the contribution and the tests!

Patch:
diff --git a/src/functions_framework/event_conversion.py b/src/functions_framework/event_conversion.py
index 28cf2a1..06e5a81 100644
--- a/src/functions_framework/event_conversion.py
+++ b/src/functions_framework/event_conversion.py
@@ -317,7 +317,7 @@ def marshal_background_event_data(request):
             "data": {
                 "@type": _PUBSUB_MESSAGE_TYPE,
                 "data": request_data["message"]["data"],
-                "attributes": request_data["message"]["attributes"],
+                "attributes": request_data["message"].get("attributes", {}),
             },
         }
     except (AttributeError, KeyError, TypeError):


Test patch:
diff --git a/tests/test_convert.py b/tests/test_convert.py
index 0d41d5e..592681e 100644
--- a/tests/test_convert.py
+++ b/tests/test_convert.py
@@ -100,6 +100,14 @@ def raw_pubsub_request():
     }
 
 
+@pytest.fixture
+def raw_pubsub_request_noattributes():
+    return {
+        "subscription": "projects/sample-project/subscriptions/gcf-test-sub",
+        "message": {"data": "eyJmb28iOiJiYXIifQ==", "messageId": "1215011316659232"},
+    }
+
+
 @pytest.fixture
 def marshalled_pubsub_request():
     return {
@@ -121,6 +129,27 @@ def marshalled_pubsub_request():
     }
 
 
+@pytest.fixture
+def marshalled_pubsub_request_noattr():
+    return {
+        "data": {
+            "@type": "type.googleapis.com/google.pubsub.v1.PubsubMessage",
+            "data": "eyJmb28iOiJiYXIifQ==",
+            "attributes": {},
+        },
+        "context": {
+            "eventId": "1215011316659232",
+            "eventType": "google.pubsub.topic.publish",
+            "resource": {
+                "name": "projects/sample-project/topics/gcf-test",
+                "service": "pubsub.googleapis.com",
+                "type": "type.googleapis.com/google.pubsub.v1.PubsubMessage",
+            },
+            "timestamp": "2021-04-17T07:21:18.249Z",
+        },
+    }
+
+
 @pytest.fixture
 def raw_pubsub_cloud_event_output(marshalled_pubsub_request):
     event = PUBSUB_CLOUD_EVENT.copy()
@@ -343,6 +372,24 @@ def test_marshal_background_event_data_without_topic_in_path(
     assert payload == marshalled_pubsub_request
 
 
+def test_marshal_background_event_data_without_topic_in_path_no_attr(
+    raw_pubsub_request_noattributes, marshalled_pubsub_request_noattr
+):
+    req = flask.Request.from_values(
+        json=raw_pubsub_request_noattributes, path="/myfunc/"
+    )
+    payload = event_conversion.marshal_background_event_data(req)
+
+    # Remove timestamps as they get generates on the fly
+    del marshalled_pubsub_request_noattr["context"]["timestamp"]
+    del payload["context"]["timestamp"]
+
+    # Resource name is set to empty string when it cannot be parsed from the request path
+    marshalled_pubsub_request_noattr["context"]["resource"]["name"] = ""
+
+    assert payload == marshalled_pubsub_request_noattr
+
+
 def test_marshal_background_event_data_with_topic_path(
     raw_pubsub_request, marshalled_pubsub_request
 ):