From 5b2a7242198c138f67d5342bb4ffa7c08e55d8c8 Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Mon, 9 Nov 2015 19:29:08 -0500 Subject: [PATCH 1/8] Check SQS message size --- moto/sqs/exceptions.py | 5 +++++ moto/sqs/models.py | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/moto/sqs/exceptions.py b/moto/sqs/exceptions.py index d72cfdffc..c9d0d73c5 100644 --- a/moto/sqs/exceptions.py +++ b/moto/sqs/exceptions.py @@ -11,6 +11,11 @@ class ReceiptHandleIsInvalid(Exception): status_code = 400 +class InvalidParameterValue(Exception): + description = "One or more parameters are invalid. Reason: Message must be shorter than 262144 bytes." + status_code = 400 + + class MessageAttributesInvalid(Exception): status_code = 400 diff --git a/moto/sqs/models.py b/moto/sqs/models.py index efb75dd9c..725465498 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -12,7 +12,8 @@ from moto.core.utils import camelcase_to_underscores, get_random_message_id from .utils import generate_receipt_handle, unix_time_millis from .exceptions import ( ReceiptHandleIsInvalid, - MessageNotInflight + MessageNotInflight, + InvalidParameterValue, ) DEFAULT_ACCOUNT_ID = 123456789012 @@ -251,6 +252,9 @@ class SQSBackend(BaseBackend): else: delay_seconds = queue.delay_seconds + if len(message_body) > self.maximum_message_size: + raise InvalidParameterValue + message_id = get_random_message_id() message = Message(message_id, message_body) From 540ee79ad9c024015936efe9fae26663ba764c7f Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Mon, 9 Nov 2015 19:51:17 -0500 Subject: [PATCH 2/8] Put the size check in the queue --- moto/sqs/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 725465498..17c33e103 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -190,6 +190,9 @@ class Queue(object): return [message for message in self._messages if message.visible and not message.delayed] def add_message(self, message): + if len(message) > self.maximum_message_size: + raise InvalidParameterValue() + self._messages.append(message) def get_cfn_attribute(self, attribute_name): @@ -252,9 +255,6 @@ class SQSBackend(BaseBackend): else: delay_seconds = queue.delay_seconds - if len(message_body) > self.maximum_message_size: - raise InvalidParameterValue - message_id = get_random_message_id() message = Message(message_id, message_body) From b732e116a4416c008211f214018ba520672ae8c1 Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Mon, 9 Nov 2015 19:53:14 -0500 Subject: [PATCH 3/8] Try the length of the body --- moto/sqs/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 17c33e103..b5a64874d 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -190,7 +190,7 @@ class Queue(object): return [message for message in self._messages if message.visible and not message.delayed] def add_message(self, message): - if len(message) > self.maximum_message_size: + if len(message.body) > self.maximum_message_size: raise InvalidParameterValue() self._messages.append(message) From f8cbcfc098b760ac58c6cb87516235d058ffa548 Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Mon, 9 Nov 2015 20:03:52 -0500 Subject: [PATCH 4/8] How about in the SQSResponse object --- moto/sqs/models.py | 4 ---- moto/sqs/responses.py | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/moto/sqs/models.py b/moto/sqs/models.py index b5a64874d..653c5316a 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -121,7 +121,6 @@ class Queue(object): self.created_timestamp = now self.delay_seconds = 0 self.last_modified_timestamp = now - self.maximum_message_size = 64 << 10 self.message_retention_period = 86400 * 4 # four days self.queue_arn = 'arn:aws:sqs:sqs.us-east-1:123456789012:%s' % self.name self.receive_message_wait_time_seconds = 0 @@ -190,9 +189,6 @@ class Queue(object): return [message for message in self._messages if message.visible and not message.delayed] def add_message(self, message): - if len(message.body) > self.maximum_message_size: - raise InvalidParameterValue() - self._messages.append(message) def get_cfn_attribute(self, attribute_name): diff --git a/moto/sqs/responses.py b/moto/sqs/responses.py index abae83fed..82d24cb6a 100644 --- a/moto/sqs/responses.py +++ b/moto/sqs/responses.py @@ -11,6 +11,7 @@ from .exceptions import ( ) MAXIMUM_VISIBILTY_TIMEOUT = 43200 +MAXIMUM_MESSAGE_LENGTH = 262144 # 256 KiB DEFAULT_RECEIVED_MESSAGES = 1 SQS_REGION_REGEX = r'://(.+?)\.queue\.amazonaws\.com' @@ -106,6 +107,9 @@ class SQSResponse(BaseResponse): message = self.querystring.get("MessageBody")[0] delay_seconds = self.querystring.get('DelaySeconds') + if len(message) > MAXIMUM_MESSAGE_LENGTH: + return "One or more parameters are invalid. Reason: Message must be shorter than 262144 bytes.", dict(status=400) + if delay_seconds: delay_seconds = int(delay_seconds[0]) else: From 97b7781c13944344c93c5deca99f918709d25bf1 Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Mon, 9 Nov 2015 20:09:08 -0500 Subject: [PATCH 5/8] Include XML response template --- moto/sqs/responses.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/moto/sqs/responses.py b/moto/sqs/responses.py index 82d24cb6a..d1ba5b6dd 100644 --- a/moto/sqs/responses.py +++ b/moto/sqs/responses.py @@ -108,7 +108,7 @@ class SQSResponse(BaseResponse): delay_seconds = self.querystring.get('DelaySeconds') if len(message) > MAXIMUM_MESSAGE_LENGTH: - return "One or more parameters are invalid. Reason: Message must be shorter than 262144 bytes.", dict(status=400) + return ERROR_TOO_LONG_RESPONSE, dict(status=400) if delay_seconds: delay_seconds = int(delay_seconds[0]) @@ -421,3 +421,13 @@ PURGE_QUEUE_RESPONSE = """ """ + +ERROR_TOO_LONG_RESPONSE = """ + + Sender + InvalidParameterValue + One or more parameters are invalid. Reason: Message must be shorter than 262144 bytes. + + + 6fde8d1e-52cd-4581-8cd9-c512f4c64223 +""" From 27e7767883153ce3aa17a9842da4fcf6c85b9f1d Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Mon, 9 Nov 2015 20:19:51 -0500 Subject: [PATCH 6/8] Remove stuff that doesn't need to change --- moto/sqs/exceptions.py | 5 ----- moto/sqs/models.py | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/moto/sqs/exceptions.py b/moto/sqs/exceptions.py index c9d0d73c5..d72cfdffc 100644 --- a/moto/sqs/exceptions.py +++ b/moto/sqs/exceptions.py @@ -11,11 +11,6 @@ class ReceiptHandleIsInvalid(Exception): status_code = 400 -class InvalidParameterValue(Exception): - description = "One or more parameters are invalid. Reason: Message must be shorter than 262144 bytes." - status_code = 400 - - class MessageAttributesInvalid(Exception): status_code = 400 diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 653c5316a..efb75dd9c 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -12,8 +12,7 @@ from moto.core.utils import camelcase_to_underscores, get_random_message_id from .utils import generate_receipt_handle, unix_time_millis from .exceptions import ( ReceiptHandleIsInvalid, - MessageNotInflight, - InvalidParameterValue, + MessageNotInflight ) DEFAULT_ACCOUNT_ID = 123456789012 @@ -121,6 +120,7 @@ class Queue(object): self.created_timestamp = now self.delay_seconds = 0 self.last_modified_timestamp = now + self.maximum_message_size = 64 << 10 self.message_retention_period = 86400 * 4 # four days self.queue_arn = 'arn:aws:sqs:sqs.us-east-1:123456789012:%s' % self.name self.receive_message_wait_time_seconds = 0 From a4e86494e13960fe604fa18bc92fbf17ec4390eb Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Tue, 10 Nov 2015 11:24:55 -0500 Subject: [PATCH 7/8] Add a test for a message that is too long --- tests/test_sqs/test_sqs.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py index a23545dcc..43ab21d5c 100644 --- a/tests/test_sqs/test_sqs.py +++ b/tests/test_sqs/test_sqs.py @@ -170,6 +170,18 @@ def test_send_message_with_delay(): queue.count().should.equal(0) +@mock_sqs +def test_send_large_message_fails(): + conn = boto.connect_sqs('the_key', 'the_secret') + queue = conn.create_queue("test-queue", visibility_timeout=60) + queue.set_message_class(RawMessage) + + body_one = 'test message' * 20000 + huge_message = queue.new_message(body_one) + + queue.write.when.called_with(huge_message).should.throw(SQSError) + + @mock_sqs def test_message_becomes_inflight_when_received(): conn = boto.connect_sqs('the_key', 'the_secret') From 5115e50bd063d4c4f2d9381ebcd39c7d711b8b2c Mon Sep 17 00:00:00 2001 From: Ian Dees Date: Tue, 10 Nov 2015 11:39:00 -0500 Subject: [PATCH 8/8] The message has to be bigger --- tests/test_sqs/test_sqs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py index 43ab21d5c..1e300fa57 100644 --- a/tests/test_sqs/test_sqs.py +++ b/tests/test_sqs/test_sqs.py @@ -176,7 +176,7 @@ def test_send_large_message_fails(): queue = conn.create_queue("test-queue", visibility_timeout=60) queue.set_message_class(RawMessage) - body_one = 'test message' * 20000 + body_one = 'test message' * 200000 huge_message = queue.new_message(body_one) queue.write.when.called_with(huge_message).should.throw(SQSError)