Ejemplo n.º 1
0
def load(req):
    """Reads request body, raising an exception if it is not JSON.

    :param req: The request object to read from
    :type req: falcon.Request
    :return: a dictionary decoded from the JSON stream
    :rtype: dict
    :raises: errors.HTTPBadRequestBody
    """
    try:
        return utils.read_json(req.stream, req.content_length)
    except (utils.MalformedJSON, utils.OverflowedJSONInteger) as ex:
        LOG.exception(ex)
        raise errors.HTTPBadRequestBody('JSON could not be parsed.')
Ejemplo n.º 2
0
def load(req):
    """Reads request body, raising an exception if it is not JSON.

    :param req: The request object to read from
    :type req: falcon.Request
    :return: a dictionary decoded from the JSON stream
    :rtype: dict
    :raises HTTPBadRequestBody: if JSON could not be parsed
    """
    try:
        return utils.read_json(req.stream, req.content_length)
    except (utils.MalformedJSON, utils.OverflowedJSONInteger) as ex:
        LOG.exception(ex)
        raise errors.HTTPBadRequestBody(
            'JSON could not be parsed.'
        )
Ejemplo n.º 3
0
def deserialize(stream, len):
    """Deserializes JSON from a file-like stream.

    This function deserializes JSON from a stream, including
    translating read and parsing errors to HTTP error types.

    :param stream: file-like object from which to read an object or
        array of objects.
    :param len: number of bytes to read from stream
    :raises HTTPBadRequest: if the request is invalid
    :raises HTTPServiceUnavailable: if the http service is unavailable
    """

    if len is None:
        description = _(u'Request body can not be empty')
        raise errors.HTTPBadRequestBody(description)

    try:
        # TODO(kgriffs): read_json should stream the resulting list
        # of messages, returning a generator rather than buffering
        # everything in memory (bp/streaming-serialization).
        return utils.read_json(stream, len)

    except utils.MalformedJSON as ex:
        LOG.debug(ex)
        description = _(u'Request body could not be parsed.')
        raise errors.HTTPBadRequestBody(description)

    except utils.OverflowedJSONInteger as ex:
        LOG.debug(ex)
        description = _(u'JSON contains integer that is too large.')
        raise errors.HTTPBadRequestBody(description)

    except Exception:
        # Error while reading from the network/server
        description = _(u'Request body could not be read.')
        LOG.exception(description)
        raise errors.HTTPServiceUnavailable(description)
Ejemplo n.º 4
0
def deserialize(stream, len):
    """Deserializes JSON from a file-like stream.

    This function deserializes JSON from a stream, including
    translating read and parsing errors to HTTP error types.

    :param stream: file-like object from which to read an object or
        array of objects.
    :param len: number of bytes to read from stream
    :raises HTTPBadRequest: if the request is invalid
    :raises HTTPServiceUnavailable: if the http service is unavailable
    """

    if len is None:
        description = _(u'Request body can not be empty')
        raise errors.HTTPBadRequestBody(description)

    try:
        # TODO(kgriffs): read_json should stream the resulting list
        # of messages, returning a generator rather than buffering
        # everything in memory (bp/streaming-serialization).
        return utils.read_json(stream, len)

    except utils.MalformedJSON as ex:
        LOG.debug(ex)
        description = _(u'Request body could not be parsed.')
        raise errors.HTTPBadRequestBody(description)

    except utils.OverflowedJSONInteger as ex:
        LOG.debug(ex)
        description = _(u'JSON contains integer that is too large.')
        raise errors.HTTPBadRequestBody(description)

    except Exception as ex:
        # Error while reading from the network/server
        LOG.exception(ex)
        description = _(u'Request body could not be read.')
        raise errors.HTTPServiceUnavailable(description)
Ejemplo n.º 5
0
    def on_patch(self, req, resp, project_id, topic_name):
        """Allows one to update a topic's metadata.

        This method expects the user to submit a JSON object. There is also
        strict format checking through the use of
        jsonschema. Appropriate errors are returned in each case for
        badly formatted input.

        :returns: HTTP | 200,400,409,503
        """
        LOG.debug(u'PATCH topic - name: %s', topic_name)

        try:
            # Place JSON size restriction before parsing
            self._validate.queue_metadata_length(req.content_length)
        except validation.ValidationFailed as ex:
            LOG.debug(ex)
            raise wsgi_errors.HTTPBadRequestBody(six.text_type(ex))

        # NOTE(flwang): See below link to get more details about draft 10,
        # tools.ietf.org/html/draft-ietf-appsawg-json-patch-10
        content_types = {
            'application/openstack-messaging-v2.0-json-patch': 10,
        }

        if req.content_type not in content_types:
            headers = {'Accept-Patch':
                       ', '.join(sorted(content_types.keys()))}
            msg = _("Accepted media type for PATCH: %s.")
            LOG.debug(msg, headers)
            raise wsgi_errors.HTTPUnsupportedMediaType(msg % headers)

        if req.content_length:
            try:
                changes = utils.read_json(req.stream, req.content_length)
                changes = wsgi_utils.sanitize(changes, doctype=list)
            except utils.MalformedJSON as ex:
                LOG.debug(ex)
                description = _(u'Request body could not be parsed.')
                raise wsgi_errors.HTTPBadRequestBody(description)

            except utils.OverflowedJSONInteger as ex:
                LOG.debug(ex)
                description = _(u'JSON contains integer that is too large.')
                raise wsgi_errors.HTTPBadRequestBody(description)

            except Exception:
                # Error while reading from the network/server
                description = _(u'Request body could not be read.')
                LOG.exception(description)
                raise wsgi_errors.HTTPServiceUnavailable(description)
        else:
            msg = _("PATCH body could not be empty for update.")
            LOG.debug(msg)
            raise wsgi_errors.HTTPBadRequestBody(msg)

        try:
            changes = self._validate.queue_patching(req, changes)

            # NOTE(Eva-i): using 'get_metadata' instead of 'get', so
            # QueueDoesNotExist error will be thrown in case of non-existent
            # queue.
            metadata = self._topic_controller.get_metadata(topic_name,
                                                           project=project_id)
            reserved_metadata = _get_reserved_metadata(self._validate)
            for change in changes:
                change_method_name = '_do_%s' % change['op']
                change_method = getattr(self, change_method_name)
                change_method(req, metadata, reserved_metadata, change)

            self._validate.queue_metadata_putting(metadata)

            self._topic_controller.set_metadata(topic_name,
                                                metadata,
                                                project_id)
        except storage_errors.DoesNotExist as ex:
            LOG.debug(ex)
            raise wsgi_errors.HTTPNotFound(six.text_type(ex))
        except validation.ValidationFailed as ex:
            LOG.debug(ex)
            raise wsgi_errors.HTTPBadRequestBody(six.text_type(ex))
        except wsgi_errors.HTTPConflict:
            raise
        except Exception:
            description = _(u'Topic could not be updated.')
            LOG.exception(description)
            raise wsgi_errors.HTTPServiceUnavailable(description)
        for meta, value in _get_reserved_metadata(self._validate).items():
            if not metadata.get(meta):
                metadata[meta] = value
        resp.body = utils.to_json(metadata)
Ejemplo n.º 6
0
    def on_patch(self, req, resp, project_id, queue_name):
        """Allows one to update a queue's metadata.

        This method expects the user to submit a JSON object. There is also
        strict format checking through the use of
        jsonschema. Appropriate errors are returned in each case for
        badly formatted input.

        :returns: HTTP | 200,400,409,503
        """
        LOG.debug(u'PATCH queue - name: %s', queue_name)

        try:
            # Place JSON size restriction before parsing
            self._validate.queue_metadata_length(req.content_length)
        except validation.ValidationFailed as ex:
            LOG.debug(ex)
            raise wsgi_errors.HTTPBadRequestBody(six.text_type(ex))

        # NOTE(flwang): See below link to get more details about draft 10,
        # tools.ietf.org/html/draft-ietf-appsawg-json-patch-10
        content_types = {
            'application/openstack-messaging-v2.0-json-patch': 10,
        }

        if req.content_type not in content_types:
            headers = {'Accept-Patch':
                       ', '.join(sorted(content_types.keys()))}
            msg = _("Accepted media type for PATCH: %s.")
            LOG.debug(msg % headers)
            raise wsgi_errors.HTTPUnsupportedMediaType(msg % headers)

        if req.content_length:
            try:
                changes = utils.read_json(req.stream, req.content_length)
                changes = wsgi_utils.sanitize(changes,
                                              spec=None, doctype=list)
            except utils.MalformedJSON as ex:
                LOG.debug(ex)
                description = _(u'Request body could not be parsed.')
                raise wsgi_errors.HTTPBadRequestBody(description)

            except utils.OverflowedJSONInteger as ex:
                LOG.debug(ex)
                description = _(u'JSON contains integer that is too large.')
                raise wsgi_errors.HTTPBadRequestBody(description)

            except Exception as ex:
                # Error while reading from the network/server
                LOG.exception(ex)
                description = _(u'Request body could not be read.')
                raise wsgi_errors.HTTPServiceUnavailable(description)
        else:
            msg = _("PATCH body could not be empty for update.")
            LOG.debug(msg)
            raise wsgi_errors.HTTPBadRequestBody(msg)

        try:
            changes = self._validate.queue_patching(req, changes)

            # NOTE(Eva-i): using 'get_metadata' instead of 'get', so
            # QueueDoesNotExist error will be thrown in case of non-existent
            # queue.
            metadata = self._queue_controller.get_metadata(queue_name,
                                                           project=project_id)
            for change in changes:
                change_method_name = '_do_%s' % change['op']
                change_method = getattr(self, change_method_name)
                change_method(req, metadata, change)

            self._validate.queue_metadata_putting(metadata)

            self._queue_controller.set_metadata(queue_name,
                                                metadata,
                                                project_id)
        except storage_errors.DoesNotExist as ex:
            LOG.debug(ex)
            raise wsgi_errors.HTTPNotFound(six.text_type(ex))
        except validation.ValidationFailed as ex:
            LOG.debug(ex)
            raise wsgi_errors.HTTPBadRequestBody(six.text_type(ex))
        except wsgi_errors.HTTPConflict as ex:
            raise ex
        except Exception as ex:
            LOG.exception(ex)
            description = _(u'Queue could not be updated.')
            raise wsgi_errors.HTTPServiceUnavailable(description)
        resp.body = utils.to_json(metadata)