Ejemplo n.º 1
0
 def test_disguised_http_exception_with_newline(self):
     wrapper = fault.FaultWrapper(None)
     newline_error = ErrorWithNewline('Error with \n newline')
     msg = wrapper._error(heat_exc.HTTPExceptionDisguise(newline_error))
     expected = {'code': 400,
                 'error': {'message': 'Error with \n newline',
                           'traceback': None,
                           'type': 'ErrorWithNewline'},
                 'explanation': ('The server could not comply with the '
                                 'request since it is either malformed '
                                 'or otherwise incorrect.'),
                 'title': 'Bad Request'}
     self.assertEqual(expected, msg)
Ejemplo n.º 2
0
    def __call__(self, request):
        """WSGI method that controls (de)serialization and method dispatch."""
        action_args = self.get_action_args(request.environ)
        action = action_args.pop('action', None)

        # From reading the boto code, and observation of real AWS api responses
        # it seems that the AWS api ignores the content-type in the html header
        # Instead it looks at a "ContentType" GET query parameter
        # This doesn't seem to be documented in the AWS cfn API spec, but it
        # would appear that the default response serialization is XML, as
        # described in the API docs, but passing a query parameter of
        # ContentType=JSON results in a JSON serialized response...
        content_type = request.params.get("ContentType")

        LOG.info("Processing request: %(method)s %(path)s",
                 {'method': request.method, 'path': request.path})

        try:
            deserialized_request = self.dispatch(self.deserializer,
                                                 action, request)
            action_args.update(deserialized_request)

            LOG.debug(('Calling %(controller)s.%(action)s'),
                      {'controller': type(self.controller).__name__,
                       'action': action})

            action_result = self.dispatch(self.controller, action,
                                          request, **action_args)
        except TypeError as err:
            LOG.error('Exception handling resource: %s', err)
            msg = _('The server could not comply with the request since '
                    'it is either malformed or otherwise incorrect.')
            err = webob.exc.HTTPBadRequest(msg)
            http_exc = translate_exception(err, request.best_match_language())
            # NOTE(luisg): We disguise HTTP exceptions, otherwise they will be
            # treated by wsgi as responses ready to be sent back and they
            # won't make it into the pipeline app that serializes errors
            raise exception.HTTPExceptionDisguise(http_exc)
        except webob.exc.HTTPException as err:
            if isinstance(err, aws_exception.HeatAPIException):
                # The AWS compatible API's don't use faultwrap, so
                # we want to detect the HeatAPIException subclasses
                # and raise rather than wrapping in HTTPExceptionDisguise
                raise
            if not isinstance(err, webob.exc.HTTPError):
                # Some HTTPException are actually not errors, they are
                # responses ready to be sent back to the users, so we don't
                # error log, disguise or translate those
                raise
            if isinstance(err, webob.exc.HTTPServerError):
                LOG.error(
                    "Returning %(code)s to user: %(explanation)s",
                    {'code': err.code, 'explanation': err.explanation})
            http_exc = translate_exception(err, request.best_match_language())
            raise exception.HTTPExceptionDisguise(http_exc)
        except exception.HeatException as err:
            raise translate_exception(err, request.best_match_language())
        except Exception as err:
            log_exception(err, sys.exc_info())
            raise translate_exception(err, request.best_match_language())
        # Here we support either passing in a serializer or detecting it
        # based on the content type.
        try:
            serializer = self.serializer
            if serializer is None:
                if content_type == "JSON":
                    serializer = serializers.JSONResponseSerializer()
                else:
                    serializer = serializers.XMLResponseSerializer()

            response = webob.Response(request=request)
            self.dispatch(serializer, action, response, action_result)
            return response

        # return unserializable result (typically an exception)
        except Exception:
            # Here we should get API exceptions derived from HeatAPIException
            # these implement get_unserialized_body(), which allow us to get
            # a dict containing the unserialized error response.
            # We only need to serialize for JSON content_type, as the
            # exception body is pre-serialized to the default XML in the
            # HeatAPIException constructor
            # If we get something else here (e.g a webob.exc exception),
            # this will fail, and we just return it without serializing,
            # which will not conform to the expected AWS error response format
            if content_type == "JSON":
                try:
                    err_body = action_result.get_unserialized_body()
                    serializer.default(action_result, err_body)
                except Exception:
                    LOG.warning("Unable to serialize exception response")

            return action_result