Ejemplo n.º 1
0
    def send_response(self, result, exc_info):

        error = None
        if exc_info is not None:
            error = serialize(exc_info[1])

        # disaster avoidance serialization check: `result` must be
        # serializable, otherwise the container will commit suicide assuming
        # unrecoverable errors (and the message will be requeued for another
        # victim)

        try:
            kombu.serialization.dumps(result, self.serializer)
        except Exception:
            exc_info = sys.exc_info()
            # `error` below is guaranteed to serialize to json
            error = serialize(UnserializableValueError(result))
            result = None

        payload = {'result': result, 'error': error}

        routing_key = self.message.properties['reply_to']
        correlation_id = self.message.properties.get('correlation_id')

        publisher = self.publisher_cls(self.amqp_uri,
                                       ssl_params=self.ssl_params)

        publisher.publish(payload,
                          serializer=self.serializer,
                          exchange=self.exchange,
                          routing_key=routing_key,
                          correlation_id=correlation_id)

        return result, exc_info
Ejemplo n.º 2
0
def test_responder_unserializable_exc(mock_publish):

    message = Mock()
    message.properties = {"reply_to": ""}

    container = Mock()
    container.config = {AMQP_URI_CONFIG_KEY: ""}

    responder = Responder(message)

    # unserialisable exception
    worker_exc = Exception(object())
    result, exc_info = responder.send_response(container, True, (Exception, worker_exc, "tb"))

    # responder will return the TypeError from json.dumps
    assert result is None
    assert exc_info == (TypeError, ANY, ANY)
    assert exc_info[1].message == ("{} is not JSON " "serializable".format(worker_exc.args[0]))

    # and publish a dictionary-serialized UnserializableValueError
    # (where the unserialisable value is a dictionary-serialized worker_exc)
    serialized_exc = serialize(worker_exc)
    expected_msg = {
        "result": None,
        "error": {
            "exc_path": "nameko.exceptions.UnserializableValueError",
            "value": "Unserializable value: `{}`".format(serialized_exc),
            "exc_type": "UnserializableValueError",
            "exc_args": (),
        },
    }
    (msg,), _ = mock_publish.call_args
    assert msg == expected_msg
Ejemplo n.º 3
0
    def handle_request(self, request):
        request.shallow = False
        try:
            context_data = self.server.context_data_from_headers(request)
            args, kwargs = self.get_entrypoint_parameters(request)

            self.check_signature(args, kwargs)
            event = Event()
            self.container.spawn_worker(
                self, args, kwargs, context_data=context_data,
                handle_result=partial(self.handle_result, event))
            result = event.wait()

            response = response_from_result(result)

        except Exception as exc:
            if (
                isinstance(exc, self.expected_exceptions) or
                isinstance(exc, BadRequest)
            ):
                status_code = 400
            else:
                status_code = 500
            error_dict = serialize(exc)
            payload = u'Error: {exc_type}: {value}\n'.format(**error_dict)

            response = Response(
                payload,
                status=status_code,
            )
        return response
Ejemplo n.º 4
0
def test_responder_unserializable_exc(mock_publish):

    message = Mock()
    message.properties = {'reply_to': ''}

    container = Mock()
    container.config = {AMQP_URI_CONFIG_KEY: ''}

    responder = Responder(message)

    # unserialisable exception
    worker_exc = Exception(object())
    result, exc_info = responder.send_response(container, True,
                                               (Exception, worker_exc, "tb"))

    # responder will return the TypeError from json.dumps
    assert result is None
    assert exc_info == (TypeError, ANY, ANY)
    assert exc_info[1].message == ("{} is not JSON "
                                   "serializable".format(worker_exc.args[0]))

    # and publish a dictionary-serialized UnserializableValueError
    # (where the unserialisable value is a dictionary-serialized worker_exc)
    serialized_exc = serialize(worker_exc)
    expected_msg = {
        'result': None,
        'error': {
            'exc_path': 'nameko.exceptions.UnserializableValueError',
            'value': 'Unserializable value: `{}`'.format(serialized_exc),
            'exc_type': 'UnserializableValueError',
            'exc_args': ()
        }
    }
    (msg, ), _ = mock_publish.call_args
    assert msg == expected_msg
Ejemplo n.º 5
0
    def handle_request(self, request):
        request.shallow = False
        try:
            context_data = self.server.context_data_from_headers(request)
            args, kwargs = self.get_entrypoint_parameters(request)

            self.check_signature(args, kwargs)
            event = Event()
            self.container.spawn_worker(self,
                                        args,
                                        kwargs,
                                        context_data=context_data,
                                        handle_result=partial(
                                            self.handle_result, event))
            result = event.wait()

            response = response_from_result(result)

        except Exception as exc:
            if (isinstance(exc, self.expected_exceptions)
                    or isinstance(exc, BadRequest)):
                status_code = 400
            else:
                status_code = 500
            error_dict = serialize(exc)
            payload = u'Error: {exc_type}: {value}\n'.format(**error_dict)

            response = Response(
                payload,
                status=status_code,
            )
        return response
Ejemplo n.º 6
0
    def send_response(self, result, exc_info, **kwargs):

        error = None
        if exc_info is not None:
            error = serialize(exc_info[1])

        # disaster avoidance serialization check: `result` must be
        # serializable, otherwise the container will commit suicide assuming
        # unrecoverable errors (and the message will be requeued for another
        # victim)

        serializer = self.config.get(SERIALIZER_CONFIG_KEY, DEFAULT_SERIALIZER)

        try:
            kombu.serialization.dumps(result, serializer)
        except Exception:
            exc_info = sys.exc_info()
            # `error` below is guaranteed to serialize to json
            error = serialize(UnserializableValueError(result))
            result = None

        conn = Connection(self.config[AMQP_URI_CONFIG_KEY])

        exchange = get_rpc_exchange(self.config)

        retry = kwargs.pop('retry', True)
        retry_policy = kwargs.pop('retry_policy', DEFAULT_RETRY_POLICY)

        with producers[conn].acquire(block=True) as producer:

            routing_key = self.message.properties['reply_to']
            correlation_id = self.message.properties.get('correlation_id')

            msg = {'result': result, 'error': error}

            _log.debug('publish response %s:%s', routing_key, correlation_id)
            producer.publish(msg,
                             retry=retry,
                             retry_policy=retry_policy,
                             exchange=exchange,
                             routing_key=routing_key,
                             serializer=serializer,
                             correlation_id=correlation_id,
                             **kwargs)

        return result, exc_info
Ejemplo n.º 7
0
    def send_response(self, result, exc_info, **kwargs):

        error = None
        if exc_info is not None:
            error = serialize(exc_info[1])

        # disaster avoidance serialization check: `result` must be
        # serializable, otherwise the container will commit suicide assuming
        # unrecoverable errors (and the message will be requeued for another
        # victim)

        serializer = self.config.get(
            SERIALIZER_CONFIG_KEY, DEFAULT_SERIALIZER)

        try:
            kombu.serialization.dumps(result, serializer)
        except Exception:
            exc_info = sys.exc_info()
            # `error` below is guaranteed to serialize to json
            error = serialize(UnserializableValueError(result))
            result = None

        conn = Connection(self.config[AMQP_URI_CONFIG_KEY])

        exchange = get_rpc_exchange(self.config)

        retry = kwargs.pop('retry', True)
        retry_policy = kwargs.pop('retry_policy', DEFAULT_RETRY_POLICY)

        with producers[conn].acquire(block=True) as producer:

            routing_key = self.message.properties['reply_to']
            correlation_id = self.message.properties.get('correlation_id')

            msg = {'result': result, 'error': error}

            _log.debug('publish response %s:%s', routing_key, correlation_id)
            producer.publish(
                msg, retry=retry, retry_policy=retry_policy,
                exchange=exchange, routing_key=routing_key,
                serializer=serializer,
                correlation_id=correlation_id, **kwargs)

        return result, exc_info
Ejemplo n.º 8
0
def test_deserialize_to_remote_error():

    exc = CustomError(u'something went ಠ_ಠ')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == u"something went ಠ_ಠ"
    assert six.text_type(deserialized) == u"CustomError something went ಠ_ಠ"
Ejemplo n.º 9
0
def test_deserialize_to_remote_error():

    exc = CustomError('something went wrong')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == "something went wrong"
    assert str(deserialized) == "CustomError something went wrong"
Ejemplo n.º 10
0
def test_serialize():

    exc = CustomError('something went wrong')

    assert serialize(exc) == {
        'exc_type': 'CustomError',
        'exc_path': 'test.test_exceptions.CustomError',
        'exc_args': ['something went wrong'],
        'value': 'something went wrong',
    }
Ejemplo n.º 11
0
def test_serialize():

    exc = CustomError('something went wrong')

    assert serialize(exc) == {
        'exc_type': 'CustomError',
        'exc_path': 'test.test_exceptions.CustomError',
        'exc_args': ['something went wrong'],
        'value': 'something went wrong',
    }
Ejemplo n.º 12
0
def test_deserialize_to_remote_error():

    exc = CustomError(u'something went ಠ_ಠ')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == u"something went ಠ_ಠ"
    assert six.text_type(deserialized) == u"CustomError something went ಠ_ಠ"
Ejemplo n.º 13
0
def test_deserialize_to_remote_error():

    exc = CustomError('something went wrong')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == "something went wrong"
    assert str(deserialized) == "CustomError something went wrong"
Ejemplo n.º 14
0
    def send_response(self, result, exc_info, **kwargs):

        error = None
        if exc_info is not None:
            error = serialize(exc_info[1])

        # disaster avoidance serialization check: `result` must be
        # serializable, otherwise the container will commit suicide assuming
        # unrecoverable errors (and the message will be requeued for another
        # victim)

        try:
            kombu.serialization.dumps(result, self.serializer)
        except Exception:
            exc_info = sys.exc_info()
            # `error` below is guaranteed to serialize to json
            error = serialize(UnserializableValueError(result))
            result = None

        exchange = get_rpc_exchange(self.config)

        retry = kwargs.pop('retry', self.retry)
        retry_policy = kwargs.pop('retry_policy', self.retry_policy)

        with get_producer(self.amqp_uri, self.use_confirms) as producer:

            routing_key = self.message.properties['reply_to']
            correlation_id = self.message.properties.get('correlation_id')

            msg = {'result': result, 'error': error}

            _log.debug('publish response %s:%s', routing_key, correlation_id)
            producer.publish(msg,
                             retry=retry,
                             retry_policy=retry_policy,
                             exchange=exchange,
                             routing_key=routing_key,
                             serializer=self.serializer,
                             correlation_id=correlation_id,
                             **kwargs)

        return result, exc_info
Ejemplo n.º 15
0
def test_deserialize_to_instance():

    # register Error as deserializable to an instance
    deserialize_to_instance(CustomError)

    exc = CustomError('something went wrong')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == CustomError
    assert str(deserialized) == "something went wrong"
Ejemplo n.º 16
0
def test_deserialize_to_instance():

    # register Error as deserializable to an instance
    deserialize_to_instance(CustomError)

    exc = CustomError('something went wrong')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == CustomError
    assert str(deserialized) == "something went wrong"
Ejemplo n.º 17
0
    def send_response(self, result, exc_info, **kwargs):
        error = None
        if exc_info is not None:
            error = serialize(exc_info[1])
            logger.warning("Sending error response %s", error)

        serializer = self.config.get(SERIALIZER_CONFIG_KEY, DEFAULT_SERIALIZER)

        try:
            kombu.serialization.dumps(result, serializer)
        except Exception:
            exc_info = sys.exc_info()
            error = serialize(UnserializableValueError(result))
            result = None

        conn = Connection(self.config[AMQP_URI_CONFIG_KEY])

        exchange = DEFAULT_EXCHANGE

        retry = kwargs.pop('retry', True)
        retry_policy = kwargs.pop('retry_policy', DEFAULT_RETRY_POLICY)

        with producers[conn].acquire(block=True) as producer:
            routing_key = self.message.properties['reply_to']
            correlation_id = self.message.properties.get('correlation_id')

            msg = {'result': result, 'error': error}

            logger.info("Sending message to %s %s: %s", exchange, routing_key,
                        msg)

            producer.publish(msg,
                             retry=retry,
                             retry_policy=retry_policy,
                             exchange=exchange,
                             routing_key=routing_key,
                             serializer=serializer,
                             correlation_id=correlation_id,
                             **kwargs)

        return result, exc_info
Ejemplo n.º 18
0
def test_exception_name_clash():
    class MethodNotFound(Exception):
        # application exception with clashing name
        pass

    exc = MethodNotFound('application error')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "MethodNotFound"
    assert deserialized.value == "application error"
    assert str(deserialized) == "MethodNotFound application error"

    from nameko.exceptions import MethodNotFound as NamekoMethodNotFound

    exc = NamekoMethodNotFound('missing')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == NamekoMethodNotFound
    assert str(deserialized) == "missing"
Ejemplo n.º 19
0
    def response_from_exception(self, exc):
        if (isinstance(exc, self.expected_exceptions)
                or isinstance(exc, BadRequest)):
            status_code = 400
        else:
            status_code = 500
        error_dict = serialize(exc)
        payload = u'Error: {exc_type}: {value}\n'.format(**error_dict)

        return Response(
            payload,
            status=status_code,
        )
Ejemplo n.º 20
0
def test_exception_name_clash():

    class MethodNotFound(Exception):
        # application exception with clashing name
        pass

    exc = MethodNotFound('application error')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "MethodNotFound"
    assert deserialized.value == "application error"
    assert str(deserialized) == "MethodNotFound application error"

    from nameko.exceptions import MethodNotFound as NamekoMethodNotFound

    exc = NamekoMethodNotFound('missing')
    data = serialize(exc)

    deserialized = deserialize(data)
    assert type(deserialized) == NamekoMethodNotFound
    assert str(deserialized) == "missing"
Ejemplo n.º 21
0
def test_serialize_cannot_unicode():
    class CannotUnicode(object):
        def __str__(self):
            raise Exception('boom')

    bad_string = CannotUnicode()
    exc = CustomError(bad_string)

    assert serialize(exc) == {
        'exc_type': 'CustomError',
        'exc_path': 'test.test_exceptions.CustomError',
        'exc_args': ['[__unicode__ failed]'],
        'value': '[__unicode__ failed]',
    }
Ejemplo n.º 22
0
def test_serialize_cannot_unicode():

    class CannotUnicode(object):
        def __str__(self):
            raise Exception('boom')

    bad_string = CannotUnicode()
    exc = CustomError(bad_string)

    assert serialize(exc) == {
        'exc_type': 'CustomError',
        'exc_path': 'test.test_exceptions.CustomError',
        'exc_args': ['[__unicode__ failed]'],
        'value': '[__unicode__ failed]',
    }
Ejemplo n.º 23
0
 def handle_request(self, request):
     try:
         result = self.get_result(request)
         return Response(
             json.dumps(result),
             status=200,
             headers=None,
         )
     except Exception as exc:
         log.error(exc)
         error_dict = serialize(exc)
         payload = u'Error: {exc_type}: {value}\n'.format(**error_dict)
         return Response(
             payload,
             status=500,
         )
    def send_response(self, message, result, exc_info):

        config = self.container.config

        error = None
        if exc_info is not None:
            error = serialize(exc_info[1])

        with get_producer(config[AMQP_URI_CONFIG_KEY]) as producer:

            routing_key = message.properties.get('reply_to')

            msg = {'result': result, 'error': error}

            producer.publish(msg,
                             exchange=orders_exchange,
                             serializer=DEFAULT_SERIALIZER,
                             routing_key=routing_key)

        return result, error
Ejemplo n.º 25
0
    def handle_websocket_request(self, socket_id, context_data, raw_req):
        correlation_id = None
        try:
            method, data, correlation_id = self.deserialize_ws_frame(raw_req)
            provider = self.get_provider_for_method(method)
            result = provider.handle_message(socket_id, data, context_data)
            response = {
                'type': 'result',
                'success': True,
                'data': result,
                'correlation_id': correlation_id,
            }

        except Exception as exc:
            error = serialize(exc)
            response = {
                'type': 'result',
                'success': False,
                'error': error,
                'correlation_id': correlation_id,
            }

        return self.serialize_for_ws(response)
Ejemplo n.º 26
0
def test_serialize_backwards_compat():

    exc = CustomError('something went wrong')
    data = serialize(exc)

    # nameko < 1.5.0 has no ``exc_path`` or ``exc_args`` keys
    del data['exc_path']
    del data['exc_args']

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == "something went wrong"
    assert str(deserialized) == "CustomError something went wrong"

    # nameko < 1.1.4 has an extra ``traceback`` key
    data['traceback'] = "traceback string"

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == "something went wrong"
    assert str(deserialized) == "CustomError something went wrong"
Ejemplo n.º 27
0
def test_serialize_backwards_compat():

    exc = CustomError('something went wrong')
    data = serialize(exc)

    # nameko < 1.5.0 has no ``exc_path`` or ``exc_args`` keys
    del data['exc_path']
    del data['exc_args']

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == "something went wrong"
    assert str(deserialized) == "CustomError something went wrong"

    # nameko < 1.1.4 has an extra ``traceback`` key
    data['traceback'] = "traceback string"

    deserialized = deserialize(data)
    assert type(deserialized) == RemoteError
    assert deserialized.exc_type == "CustomError"
    assert deserialized.value == "something went wrong"
    assert str(deserialized) == "CustomError something went wrong"
Ejemplo n.º 28
0
    def handle_websocket_request(self, socket_id, context_data, raw_req):
        correlation_id = None
        try:
            method, data, correlation_id = self.deserialize_ws_frame(
                raw_req)
            provider = self.get_provider_for_method(method)
            result = provider.handle_message(socket_id, data, context_data)
            response = {
                'type': 'result',
                'success': True,
                'data': result,
                'correlation_id': correlation_id,
            }

        except Exception as exc:
            error = serialize(exc)
            response = {
                'type': 'result',
                'success': False,
                'error': error,
                'correlation_id': correlation_id,
            }

        return self.serialize_for_ws(response)
Ejemplo n.º 29
0
def test_serialize_args():
    cause = Exception('oops')
    exc = CustomError('something went wrong', cause)

    assert json.dumps(serialize(exc))
Ejemplo n.º 30
0
def test_serialize_args():
    cause = Exception('oops')
    exc = CustomError('something went wrong', cause)

    assert json.dumps(serialize(exc))