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.')
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.' )
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)
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)
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)
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)