01
Inspect the configured delivery shape
Compare a redacted request shape with the subscription settings. Wrapped push delivery places message data in a JSON envelope. Payload unwrapping changes that HTTP body contract, so a handler written for one mode should not guess which mode arrived.
Our fixture contained message, messageId, and subscription metadata around a Base64 data value. Reading envelope["order_id"] failed, while the decoded data object contained that field. Authentication and parser behavior are separate concerns; a correctly shaped request is not proof of a trusted sender.
02
Validate the wrapper before decoding
Check that the top-level value and message are objects and that data is a string. This guide assumes the publisher sends a JSON business object in message data. An attributes-only message or a different payload format needs its own explicit contract.
The parser below rejects unexpected shapes, invalid Base64, invalid UTF-8, and invalid JSON. It intentionally leaves request-size limits, sender verification, and business-field validation to the surrounding endpoint.
import base64
import json
def decode_wrapped(body):
if not isinstance(body, dict):
raise ValueError("Expected object envelope")
message = body.get("message")
if not isinstance(message, dict) or not isinstance(message.get("data"), str):
raise ValueError("Expected message.data string")
raw = base64.b64decode(message["data"], validate=True)
return json.loads(raw.decode("utf-8"))03
Check the business schema after transport decoding
JSON can legally decode to a list, number, or null. Do not assume that successful JSON parsing guarantees an order object. Check the fields and types your application requires before invoking a side effect.
The following narrow validator only checks a non-empty order identifier. Real applications may require more fields and domain rules. Keep metadata such as message identifiers available separately for tracing without confusing it with business identity.
def require_order(payload):
if not isinstance(payload, dict):
raise ValueError("Expected order object")
order_id = payload.get("order_id")
if not isinstance(order_id, str) or not order_id.strip():
raise ValueError("Expected order_id")
return order_id04
Handle errors and acknowledgements deliberately
Do not return a success response before the processing outcome that the application intends to acknowledge. Pub/Sub treats supported successful response codes as acknowledgement; unsuccessful responses can lead to redelivery. Invalid messages therefore need an intentional retry or poison-message policy.
These decoder functions do not supply that policy and do not implement authenticated push verification. Decide those in the actual endpoint rather than treating a generic exception handler that always returns 200 as a parser fix.
05
Test a matrix of payloads
Our local checks rejected a non-object envelope, missing message.data, malformed Base64, a non-UTF-8 payload, and text that was not JSON. The valid fixture produced the original order object. Also test the business validator with a JSON list, missing ID, and empty ID.
For a real subscription, verify its wrapping mode, authentication, and a controlled processing result independently. A local parser test cannot prove that the public endpoint is reachable or that Google Cloud accepted its acknowledgement.
Sınırları bil
Tested with local wrapped-message fixtures, including missing fields, invalid Base64, invalid UTF-8, and invalid JSON. The valid fixture decoded to the expected order. These tests did not exercise Pub/Sub push delivery, JWT verification, retries, or service acknowledgements.
Kaynaklar ve ileri okuma
CoreTrailKit tarafından hazırlanan teknik yayın.
Bütün yazıları keşfet