Skip to content

fix(pubsub): accept messages from requests without CloudEvent headers - #334

Draft
IzaakGough wants to merge 1 commit into
mainfrom
fix/pubsub-message-without-cloudevent-headers
Draft

IzaakGough wants to merge 1 commit into
mainfrom
fix/pubsub-message-without-cloudevent-headers

Conversation

@IzaakGough

Copy link
Copy Markdown
Contributor

Fixes #333.

When a Pub/Sub request reached an on_message_published function without CloudEvent headers, the function failed with KeyError: 'publish_time' before the handler ran.

This accepts the message that functions-framework builds for those requests, matching how the Node SDK reads it.

  • MessagePublishedData.subscription is now str | None. The request has no subscription on this path, and leaving the type as str would hide that.

Tested with a unit test using functions-framework's conversion and with the issue's MRE locally. Not tested with a real Eventarc delivery.

functions-framework converts such requests itself, producing a message with
only camelCase keys, an "@type" key and no subscription, which made
on_message_published raise KeyError: 'publish_time'.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for Pub/Sub push requests that lack CloudEvent headers by mapping camelCase keys to snake_case and making the subscription field optional. A test case is also added to verify this behavior. The review feedback suggests checking for the existence of camelCase keys before calling setdefault to prevent injecting None values, which could lead to downstream errors.

Comment on lines +112 to +113
message_dict.setdefault("message_id", message_dict.get("messageId"))
message_dict.setdefault("publish_time", message_dict.get("publishTime"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using message_dict.get() here will return None if the camelCase keys are missing. If both the snake_case and camelCase keys are absent (e.g., in a malformed request), setdefault will set the keys to None. This can lead to confusing downstream errors, such as a TypeError: argument of type 'NoneType' is not iterable when checking for . in publish_time on line 119, instead of a standard KeyError. Checking for the existence of the camelCase keys before calling setdefault avoids injecting None values.

Suggested change
message_dict.setdefault("message_id", message_dict.get("messageId"))
message_dict.setdefault("publish_time", message_dict.get("publishTime"))
if "messageId" in message_dict:
message_dict.setdefault("message_id", message_dict["messageId"])
if "publishTime" in message_dict:
message_dict.setdefault("publish_time", message_dict["publishTime"])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

on_message_published raises KeyError: 'publish_time' when functions_framework falls back to converting a raw Pub/Sub push

1 participant