Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
sqs.message: Raising an exception in decode() should not abort parsing
Browse files Browse the repository at this point in the history
Since AWS seems to return Body before ReceiptHandle, raising an exception in decode() will abort processing before the receipt handle is read.

This is a problem, because there's no way to dequeue the message without the handle.

Instead, wait to invoke decode() until parsing is finished.
  • Loading branch information
Paul Melnikow committed Oct 31, 2013
1 parent ed669f7 commit cdef0b4
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
2 changes: 2 additions & 0 deletions boto/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def startElement(self, name, attrs):
def endElement(self, name):
self.nodes[-1][1].endElement(name, self.current_text, self.connection)
if self.nodes[-1][0] == name:
if hasattr(self.nodes[-1][1], 'endNode'):
self.nodes[-1][1].endNode(self.connection)
self.nodes.pop()
self.current_text = ''

Expand Down
5 changes: 4 additions & 1 deletion boto/sqs/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def startElement(self, name, attrs, connection):

def endElement(self, name, value, connection):
if name == 'Body':
self.set_body(self.decode(value))
self.set_body(value)
elif name == 'MessageId':
self.id = value
elif name == 'ReceiptHandle':
Expand All @@ -105,6 +105,9 @@ def endElement(self, name, value, connection):
else:
setattr(self, name, value)

def endNode(self, connection):
self.set_body(self.decode(self.get_body()))

def encode(self, value):
"""Transform body object into serialized byte array format."""
return value
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/sqs/test_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from tests.unit import unittest

from boto.sqs.message import MHMessage
from boto.sqs.message import RawMessage
from boto.exception import SQSDecodeError


class TestMHMessage(unittest.TestCase):
Expand All @@ -31,5 +33,34 @@ def test_contains(self):
self.assertTrue('hello' in msg)


class DecodeExceptionRaisingMessage(RawMessage):
def decode(self, message):
raise SQSDecodeError('Sample decode error', self)

class TestEncodeMessage(unittest.TestCase):

def test_message_id_available(self):
import xml.sax
from boto.resultset import ResultSet
from boto.handler import XmlHandler
sample_value = 'abcdef'
body = """<?xml version="1.0"?>
<ReceiveMessageResponse>
<ReceiveMessageResult>
<Message>
<Body>%s</Body>
<ReceiptHandle>%s</ReceiptHandle>
<MessageId>%s</MessageId>
</Message>
</ReceiveMessageResult>
</ReceiveMessageResponse>""" % tuple([sample_value] * 3)
rs = ResultSet([('Message', DecodeExceptionRaisingMessage)])
h = XmlHandler(rs, None)
with self.assertRaises(SQSDecodeError) as context:
xml.sax.parseString(body, h)
message = context.exception.message
self.assertEquals(message.id, sample_value)
self.assertEquals(message.receipt_handle, sample_value)

if __name__ == '__main__':
unittest.main()

0 comments on commit cdef0b4

Please sign in to comment.