From 96e87a1ea987b4dbeeb834bf12af690227c6d584 Mon Sep 17 00:00:00 2001 From: Thomas Herve Date: Thu, 30 Jul 2015 11:39:03 +0200 Subject: [PATCH] Fix validation errors handling in websocket Make sanitize raises correct BadRequest exceptions in api utils. Change-Id: I58e77b6f89a3a511f71c2c6074f7be9a4fbdd7c5 Closes-Bug: #1479687 --- zaqar/api/v1_1/endpoints.py | 11 +++-- zaqar/common/api/errors.py | 6 +-- zaqar/common/api/utils.py | 8 ++-- .../transport/websocket/v1_1/test_messages.py | 41 +++++++++++++++++++ 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/zaqar/api/v1_1/endpoints.py b/zaqar/api/v1_1/endpoints.py index 881d10ec..1e86314a 100644 --- a/zaqar/api/v1_1/endpoints.py +++ b/zaqar/api/v1_1/endpoints.py @@ -382,9 +382,14 @@ class Endpoints(object): ('body', '*', None), ) - messages = api_utils.sanitize(messages, - _message_post_spec, - doctype=list) + try: + messages = api_utils.sanitize(messages, + _message_post_spec, + doctype=list) + except api_errors.BadRequest as ex: + LOG.debug(ex) + headers = {'status': 400} + return api_utils.error_response(req, ex, headers) try: client_uuid = api_utils.get_client_uuid(req) diff --git a/zaqar/common/api/errors.py b/zaqar/common/api/errors.py index f70c1846..f63a1d1d 100644 --- a/zaqar/common/api/errors.py +++ b/zaqar/common/api/errors.py @@ -26,15 +26,15 @@ class ExceptionBase(Exception): class BadRequest(ExceptionBase): """Raised when an invalid request is received.""" - msg_format = u'Bad request. {error} {description}' + msg_format = u'Bad request. {description}' - def __init__(self, error, description): + def __init__(self, description): """Initializes the error with contextual information. :param description: Error description """ - super(BadRequest, self).__init__(error=error, description=description) + super(BadRequest, self).__init__(description=description) class DocumentTypeNotSupported(ExceptionBase): diff --git a/zaqar/common/api/utils.py b/zaqar/common/api/utils.py index 47b363a1..6f1e2bf0 100644 --- a/zaqar/common/api/utils.py +++ b/zaqar/common/api/utils.py @@ -54,7 +54,7 @@ def sanitize(document, spec=None, doctype=dict): if not isinstance(document, dict): raise api_errors.DocumentTypeNotSupported() - return document if spec is None else filter(document, spec) + return document if spec is None else filter_fields(document, spec) if doctype is list: if not isinstance(document, list): @@ -63,12 +63,12 @@ def sanitize(document, spec=None, doctype=dict): if spec is None: return document - return [filter(obj, spec) for obj in document] + return [filter_fields(obj, spec) for obj in document] raise TypeError(_(u'Doctype must be either a JSONObject or JSONArray')) -def filter(document, spec): +def filter_fields(document, spec): """Validates and retrieves typed fields from a single document. Sanitizes a dict-like document by checking it against a @@ -143,7 +143,7 @@ def get_client_uuid(req): return uuid.UUID(req._headers.get('Client-ID')) except ValueError: description = _(u'Malformed hexadecimal UUID.') - raise api_errors.BadRequest(_(u'Wrong UUID value'), description) + raise api_errors.BadRequest(description) def get_headers(req): diff --git a/zaqar/tests/unit/transport/websocket/v1_1/test_messages.py b/zaqar/tests/unit/transport/websocket/v1_1/test_messages.py index 5222a4bf..31c70d7a 100644 --- a/zaqar/tests/unit/transport/websocket/v1_1/test_messages.py +++ b/zaqar/tests/unit/transport/websocket/v1_1/test_messages.py @@ -278,6 +278,47 @@ class MessagesBaseTest(base.V1_1Base): resp = self._post_messages(queue_name) self.assertEqual(resp['headers']['status'], 201) + def test_post_invalid_ttl(self): + sample_messages = [ + {'body': {'key': 'value'}, 'ttl': '200'}, + ] + + action = "message_post" + body = {"queue_name": "kitkat", + "messages": sample_messages} + + send_mock = mock.patch.object(self.protocol, 'sendMessage') + self.addCleanup(send_mock.stop) + send_mock = send_mock.start() + + req = test_utils.create_request(action, body, self.headers) + self.protocol.onMessage(req, False) + resp = json.loads(send_mock.call_args[0][0]) + self.assertEqual(400, resp['headers']['status']) + self.assertEqual( + 'Bad request. The value of the "ttl" field must be a int.', + resp['body']['exception']) + + def test_post_no_body(self): + sample_messages = [ + {'ttl': 200}, + ] + + action = "message_post" + body = {"queue_name": "kitkat", + "messages": sample_messages} + + send_mock = mock.patch.object(self.protocol, 'sendMessage') + self.addCleanup(send_mock.stop) + send_mock = send_mock.start() + + req = test_utils.create_request(action, body, self.headers) + self.protocol.onMessage(req, False) + resp = json.loads(send_mock.call_args[0][0]) + self.assertEqual(400, resp['headers']['status']) + self.assertEqual( + 'Bad request. Missing "body" field.', resp['body']['exception']) + def test_get_from_missing_queue(self): action = "message_list" body = {"queue_name": "anothernonexistent"}