8000 fix SNS headers when publishing to HTTP endpoints (#9323) · codeperl/localstack@5716c17 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5716c17

Browse files
authored
fix SNS headers when publishing to HTTP endpoints (localstack#9323)
1 parent d4f38c2 commit 5716c17

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

localstack/services/sns/publisher.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -403,23 +403,24 @@ def _publish(self, context: SnsPublishContext, subscriber: SnsSubscription):
403403
message_body = self.prepare_message(message_context, subscriber)
404404
try:
405405
message_headers = {
406-
"Content-Type": "text/plain",
406+
"Content-Type": "text/plain; charset=UTF-8",
407+
"Accept-Encoding": "gzip,deflate",
408+
"User-Agent": "Amazon Simple Notification Service Agent",
407409
# AWS headers according to
408410
# https://docs.aws.amazon.com/sns/latest/dg/sns-message-and-json-formats.html#http-header
409411
"x-amz-sns-message-type": message_context.type,
410412
"x-amz-sns-message-id": message_context.message_id,
411413
"x-amz-sns-topic-arn": subscriber["TopicArn"],
412-
"User-Agent": "Amazon Simple Notification Service Agent",
413414
}
414415
if message_context.type != "SubscriptionConfirmation":
415416
# while testing, never had those from AWS but the docs above states it should be there
416417
message_headers["x-amz-sns-subscription-arn"] = subscriber["SubscriptionArn"]
417418

418-
# When raw message delivery is enabled, x-amz-sns-rawdelivery needs to be set to 'true'
419-
# indicating that the message has been published without JSON formatting.
420-
# https://docs.aws.amazon.com/sns/latest/dg/sns-large-payload-raw-message-delivery.html
421-
elif message_context.type == "Notification" and is_raw_message_delivery(subscriber):
422-
message_headers["x-amz-sns-rawdelivery"] = "true"
419+
# When raw message delivery is enabled, x-amz-sns-rawdelivery needs to be set to 'true'
420+
# indicating that the message has been published without JSON formatting.
421+
# https://docs.aws.amazon.com/sns/latest/dg/sns-large-payload-raw-message-delivery.html
422+
if message_context.type == "Notification" and is_raw_message_delivery(subscriber):
423+
message_headers["x-amz-sns-rawdelivery"] = "true"
423424

424425
response = requests.post(
425426
subscriber["Endpoint"],

tests/aws/services/sns/test_sns.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,6 +3523,12 @@ def handler(_request):
35233523

35243524
@markers.aws.manual_setup_required
35253525
@pytest.mark.parametrize("raw_message_delivery", [True, False])
3526+
@markers.snapshot.skip_snapshot_verify(
3527+
paths=[
3528+
"$.http-message-headers.Accept", # requests adds the header but not SNS, not very important
3529+
"$.http-message-headers-raw.Accept", # requests adds the header but not SNS, not very important
3530+
]
3531+
)
35263532
def test_subscribe_external_http_endpoint(
35273533
self, sns_create_http_endpoint, raw_message_delivery, aws_client, snapshot
35283534
):
@@ -3535,10 +3541,20 @@ def _get_snapshot_requests_response(response: requests.Response) -> dict:
35353541
fields["ResponseMetadata"]["HTTPStatusCode"] = response.status_code
35363542
return parsed_xml_body
35373543

3544+
def _clean_headers(response_headers: dict):
3545+
return {key: val for key, val in response_headers.items() if "Forwarded" not in key}
3546+
35383547
snapshot.add_transformer(
35393548
[
35403549
snapshot.transform.key_value("RequestId"),
35413550
snapshot.transform.key_value("Token"),
3551+
snapshot.transform.key_value("Host"),
3552+
snapshot.transform.key_value(
3553+
"Content-Length", reference_replacement=False
3554+
), # might change depending on compression
3555+
snapshot.transform.key_value(
3556+
"Connection", reference_replacement=False
3557+
), # casing might change
35423558
snapshot.transform.regex(
35433559
r"(?i)(?<=SubscribeURL[\"|']:\s[\"|'])(https?.*?)(?=/\?Action=ConfirmSubscription)",
35443560
replacement="<subscribe-domain>",
@@ -3651,6 +3667,7 @@ def _get_snapshot_requests_response(response: requests.Response) -> dict:
36513667
if raw_message_delivery:
36523668
payload = notification_request.data.decode()
36533669
assert payload == message
3670+
snapshot.match("http-message-headers-raw", _clean_headers(notification_request.headers))
36543671
else:
36553672
payload = notification_request.get_json(force=True)
36563673
assert payload["Type"] == "Notification"
@@ -3659,6 +3676,7 @@ def _get_snapshot_requests_response(response: requests.Response) -> dict:
36593676
assert payload["Message"] == message
36603677
assert payload["UnsubscribeURL"] == expected_unsubscribe_url
36613678
snapshot.match("http-message", payload)
3679+
snapshot.match("http-message-headers", _clean_headers(notification_request.headers))
36623680

36633681
unsub_request = requests.get(expected_unsubscribe_url)
36643682
unsubscribe_confirmation = xmltodict.parse(unsub_request.content)

tests/aws/services/sns/test_sns.snapshot.json

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4284,7 +4284,7 @@
42844284
}
42854285
},
42864286
"tests/aws/services/sns/test_sns.py::TestSNSSubscriptionHttp::test_subscribe_external_http_endpoint[True]": {
4287-
"recorded-date": "25-08-2023, 17:28:02",
4287+
"recorded-date": "09-10-2023, 16:01:30",
42884288
"recorded-content": {
42894289
"subscription-confirmation": {
42904290
"Message": "You have chosen to subscribe to the topic arn:aws:sns:<region>:111111111111:<resource:1>.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
@@ -4350,6 +4350,19 @@
43504350
}
43514351
}
43524352
},
4353+
"http-message-headers-raw": {
4354+
"Accept-Encoding": "gzip,deflate",
4355+
"Connection": "connection",
4356+
"Content-Length": "content--length",
4357+
"Content-Type": "text/plain; charset=UTF-8",
4358+
"Host": "<host:1>",
4359+
"User-Agent": "Amazon Simple Notification Service Agent",
4360+
"X-Amz-Sns-Message-Id": "<uuid:2>",
4361+
"X-Amz-Sns-Message-Type": "Notification",
4362+
"X-Amz-Sns-Rawdelivery": "true",
4363+
"X-Amz-Sns-Subscription-Arn": "arn:aws:sns:<region>:111111111111:<resource:1>:<resource:2>",
4364+
"X-Amz-Sns-Topic-Arn": "arn:aws:sns:<region>:111111111111:<resource:1>"
4365+
},
43534366
"unsubscribe-response": {
43544367
"UnsubscribeResponse": {
43554368
"ResponseMetadata": {
@@ -4360,7 +4373,7 @@
43604373
},
43614374
"unsubscribe-request": {
43624375
"Message": "You have chosen to deactivate subscription arn:aws:sns:<region>:111111111111:<resource:1>:<resource:2>.\nTo cancel this operation and restore the subscription, visit the SubscribeURL included in this message.",
4363-
"MessageId": "<uuid:2>",
4376+
"MessageId": "<uuid:3>",
43644377
"Signature": "<signature>",
43654378
"SignatureVersion": "1",
43664379
"SigningCertURL": "https://sns.<region>.amazonaws.com/SimpleNotificationService-<signing-cert-file:1>",
@@ -4373,7 +4386,7 @@
43734386
}
43744387
},
43754388
"tests/aws/services/sns/test_sns.py::TestSNSSubscriptionHttp::test_subscribe_external_http_endpoint[False]": {
4376-
"recorded-date": "25-08-2023, 17:28:08",
4389+
"recorded-date": "09-10-2023, 16:01:39",
43774390
"recorded-content": {
43784391
"subscription-confirmation": {
43794392
"Message": "You have chosen to subscribe to the topic arn:aws:sns:<region>:111111111111:<resource:1>.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
@@ -4450,6 +4463,18 @@
44504463
"Type": "Notification",
44514464
"UnsubscribeURL": "<unsubscribe-domain>/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:<region>:111111111111:<resource:1>:<resource:2>"
44524465
},
4466+
"http-message-headers": {
4467+
"Accept-Encoding": "gzip,deflate",
4468+
"Connection": "connection",
4469+
"Content-Length": "content--length",
4470+
"Content-Type": "text/plain; charset=UTF-8",
4471+
"Host": "<host:1>",
4472+
"User-Agent": "Amazon Simple Notification Service Agent",
4473+
"X-Amz-Sns-Message-Id": "<uuid:2>",
4474+
"X-Amz-Sns-Message-Type": "Notification",
4475+
"X-Amz-Sns-Subscription-Arn": "arn:aws:sns:<region>:111111111111:<resource:1>:<resource:2>",
4476+
"X-Amz-Sns-Topic-Arn": "arn:aws:sns:<region>:111111111111:<resource:1>"
4477+
},
44534478
"unsubscribe-response": {
44544479
"UnsubscribeResponse": {
44554480
"ResponseMetadata": {

0 commit comments

Comments
 (0)
0