Skip to content

Commit bc6f7f7

Browse files
authored
add error message for invalid SQS batch message IDs (#7015)
1 parent 0adb297 commit bc6f7f7

File tree

4 files changed

+91
-3
lines changed

4 files changed

+91
-3
lines changed

localstack/services/awslambda/event_source_listeners/sqs_event_source_listener.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,14 @@ def delete_messages(result: InvocationResult, func_arn, event, error=None, **kwa
156156
return
157157

158158
entries = [
159-
{"Id": r["receiptHandle"], "ReceiptHandle": r["receiptHandle"]}
159+
{"Id": r["messageId"], "ReceiptHandle": r["receiptHandle"]}
160160
for r in records
161161
if r["messageId"] in messages_to_delete
162162
]
163163

164164
else:
165165
entries = [
166-
{"Id": r["receiptHandle"], "ReceiptHandle": r["receiptHandle"]} for r in records
166+
{"Id": r["messageId"], "ReceiptHandle": r["receiptHandle"]} for r in records
167167
]
168168

169169
try:

localstack/services/sqs/provider.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
GetQueueUrlResult,
3535
Integer,
3636
InvalidAttributeName,
37+
InvalidBatchEntryId,
3738
InvalidMessageContents,
3839
ListDeadLetterSourceQueuesResult,
3940
ListQueuesResult,
@@ -725,6 +726,7 @@ def delete_message_batch(
725726
) -> DeleteMessageBatchResult:
726727
queue = self._resolve_queue(context, queue_url=queue_url)
727728
self._assert_batch(entries)
729+
self._assert_valid_message_ids(entries)
728730

729731
successful = []
730732
failed = []
@@ -894,6 +896,15 @@ def _assert_valid_batch_size(self, batch: List, max_message_size: int):
894896
error += f" You have sent {batch_message_size} bytes."
895897
raise BatchRequestTooLong(error)
896898

899+
def _assert_valid_message_ids(self, batch: List):
900+
batch_id_regex = r"^[\w-]{1,80}$"
901+
for message in batch:
902+
if not re.match(batch_id_regex, message.get("Id", "")):
903+
raise InvalidBatchEntryId(
904+
"A batch entry id can only contain alphanumeric characters, "
905+
"hyphens and underscores. It can be at most 80 letters long."
906+
)
907+
897908

898909
# Method from moto's attribute_md5 of moto/sqs/models.py, separated from the Message Object
899910
def _create_message_attribute_hash(message_attributes) -> Optional[str]:

tests/integration/test_sqs.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import re
44
import time
55
from threading import Timer
6+
from typing import Dict
67

78
import pytest
89
import requests
@@ -13,6 +14,7 @@
1314
from localstack.aws.api.lambda_ import Runtime
1415
from localstack.services.sqs.constants import DEFAULT_MAXIMUM_MESSAGE_SIZE
1516
from localstack.services.sqs.models import sqs_stores
17+
from localstack.testing.snapshots.transformer import GenericTransformer
1618
from localstack.utils.aws import aws_stack
1719
from localstack.utils.common import poll_condition, retry, short_uid, to_str
1820

@@ -1298,6 +1300,23 @@ def test_publish_get_delete_message_batch(self, sqs_client, sqs_create_queue):
12981300
)
12991301
assert "Messages" not in confirmation.keys()
13001302

1303+
@pytest.mark.aws_validated
1304+
@pytest.mark.parametrize(
1305+
argnames="invalid_message_id", argvalues=["", "testLongId" * 10, "invalid:id"]
1306+
)
1307+
def test_delete_message_batch_invalid_msg_id(
1308+
self, invalid_message_id, sqs_create_queue, sqs_client, snapshot
1309+
):
1310+
self._add_error_detail_transformer(snapshot)
1311+
1312+
queue_name = f"queue-{short_uid()}"
1313+
queue_url = sqs_create_queue(QueueName=queue_name)
1314+
1315+
delete_entries = [{"Id": invalid_message_id, "ReceiptHandle": "testHandle1"}]
1316+
with pytest.raises(ClientError) as e:
1317+
sqs_client.delete_message_batch(QueueUrl=queue_url, Entries=delete_entries)
1318+
snapshot.match("error_response", e.value.response)
1319+
13011320
@pytest.mark.aws_validated
13021321
def test_create_and_send_to_fifo_queue(self, sqs_client, sqs_create_queue):
13031322
# Old name: test_create_fifo_queue
@@ -2612,6 +2631,16 @@ def test_delete_message_with_deleted_receipt_handle(self, sqs_client, sqs_queue)
26122631

26132632
# TODO: test message attributes and message system attributes
26142633

2634+
def _add_error_detail_transformer(self, snapshot):
2635+
"""Adds a transformer to ignore {"Error": {"Detail": None, ...}} entries in snapshot error responses"""
2636+
2637+
def _remove_error_details(snapshot_content: Dict, *args) -> Dict:
2638+
for response in snapshot_content.values():
2639+
response.get("Error", {}).pop("Detail", None)
2640+
return snapshot_content
2641+
2642+
snapshot.add_transformer(GenericTransformer(_remove_error_details))
2643+
26152644

26162645
def get_region():
26172646
return os.environ.get("AWS_DEFAULT_REGION") or TEST_REGION

tests/integration/test_sqs.snapshot.json

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,5 +525,53 @@
525525
]
526526
}
527527
}
528+
},
529+
"tests/integration/test_sqs.py::TestSqsProvider::test_delete_message_batch_invalid_msg_id[]": {
530+
"recorded-date": "13-10-2022, 19:19:31",
531+
"recorded-content": {
532+
"error_response": {
533+
"Error": {
534+
"Code": "AWS.SimpleQueueService.InvalidBatchEntryId",
535+
"Message": "A batch entry id can only contain alphanumeric characters, hyphens and underscores. It can be at most 80 letters long.",
536+
"Type": "Sender"
537+
},
538+
"ResponseMetadata": {
539+
"HTTPHeaders": {},
540+
"HTTPStatusCode": 400
541+
}
542+
}
543+
}
544+
},
545+
"tests/integration/test_sqs.py::TestSqsProvider::test_delete_message_batch_invalid_msg_id[testLongIdtestLongIdtestLongIdtestLongIdtestLongIdtestLongIdtestLongIdtestLongIdtestLongIdtestLongId]": {
546+
"recorded-date": "13-10-2022, 19:19:31",
547+
"recorded-content": {
548+
"error_response": {
549+
"Error": {
550+
"Code": "AWS.SimpleQueueService.InvalidBatchEntryId",
551+
"Message": "A batch entry id can only contain alphanumeric characters, hyphens and underscores. It can be at most 80 letters long.",
552+
"Type": "Sender"
553+
},
554+
"ResponseMetadata": {
555+
"HTTPHeaders": {},
556+
"HTTPStatusCode": 400
557+
}
558+
}
559+
}
560+
},
561+
"tests/integration/test_sqs.py::TestSqsProvider::test_delete_message_batch_invalid_msg_id[invalid:id]": {
562+
"recorded-date": "13-10-2022, 19:19:32",
563+
"recorded-content": {
564+
"error_response": {
565+
"Error": {
566+
"Code": "AWS.SimpleQueueService.InvalidBatchEntryId",
567+
"Message": "A batch entry id can only contain alphanumeric characters, hyphens and underscores. It can be at most 80 letters long.",
568+
"Type": "Sender"
569+
},
570+
"ResponseMetadata": {
571+
"HTTPHeaders": {},
572+
"HTTPStatusCode": 400
573+
}
574+
}
575+
}
528576
}
529-
}
577+
}

0 commit comments

Comments
 (0)