def setUp(self): super(NetforceWebTestCase, self).setUp() json_deserializer = wsgi.JSONDeserializer() self._deserializers = { 'application/json': json_deserializer, }
def test_json_with_unicode(self): data = b'{"a": "\u7f51\u7edc"}' as_dict = {'body': {'a': u'\u7f51\u7edc'}} deserializer = wsgi.JSONDeserializer() self.assertEqual(as_dict, deserializer.deserialize(data))
def Resource(controller, faults=None, deserializers=None, serializers=None): """Represents an API entity resource and the associated serialization and deserialization logic """ default_deserializers = {'application/json': wsgi.JSONDeserializer()} default_serializers = {'application/json': wsgi.JSONDictSerializer()} format_types = {'json': 'application/json'} action_status = dict(create=201, delete=204) default_deserializers.update(deserializers or {}) default_serializers.update(serializers or {}) deserializers = default_deserializers serializers = default_serializers faults = faults or {} @webob.dec.wsgify(RequestClass=Request) def resource(request): route_args = request.environ.get('wsgiorg.routing_args') if route_args: args = route_args[1].copy() else: args = {} # NOTE(jkoelker) by now the controller is already found, remove # it from the args if it is in the matchdict args.pop('controller', None) fmt = args.pop('format', None) action = args.pop('action', None) content_type = format_types.get(fmt, request.best_match_content_type()) language = request.best_match_language() deserializer = deserializers.get(content_type) serializer = serializers.get(content_type) try: if request.body: args['body'] = deserializer.deserialize(request.body)['body'] method = getattr(controller, action) result = method(request=request, **args) except (exceptions.NeutronException, netaddr.AddrFormatError, oslo_policy.PolicyNotAuthorized) as e: for fault in faults: if isinstance(e, fault): mapped_exc = faults[fault] break else: mapped_exc = webob.exc.HTTPInternalServerError if 400 <= mapped_exc.code < 500: LOG.info(_LI('%(action)s failed (client error): %(exc)s'), {'action': action, 'exc': e}) else: LOG.exception(_LE('%s failed'), action) e = translate(e, language) body = serializer.serialize( {'NeutronError': get_exception_data(e)}) kwargs = {'body': body, 'content_type': content_type} raise mapped_exc(**kwargs) except webob.exc.HTTPException as e: type_, value, tb = sys.exc_info() if hasattr(e, 'code') and 400 <= e.code < 500: LOG.info(_LI('%(action)s failed (client error): %(exc)s'), {'action': action, 'exc': e}) else: LOG.exception(_LE('%s failed'), action) translate(e, language) value.body = serializer.serialize( {'NeutronError': get_exception_data(e)}) value.content_type = content_type six.reraise(type_, value, tb) except NotImplementedError as e: e = translate(e, language) # NOTE(armando-migliaccio): from a client standpoint # it makes sense to receive these errors, because # extensions may or may not be implemented by # the underlying plugin. So if something goes south, # because a plugin does not implement a feature, # returning 500 is definitely confusing. body = serializer.serialize( {'NotImplementedError': get_exception_data(e)}) kwargs = {'body': body, 'content_type': content_type} raise webob.exc.HTTPNotImplemented(**kwargs) except Exception: # NOTE(jkoelker) Everything else is 500 LOG.exception(_LE('%s failed'), action) # Do not expose details of 500 error to clients. msg = _('Request Failed: internal server error while ' 'processing your request.') msg = translate(msg, language) body = serializer.serialize( {'NeutronError': get_exception_data( webob.exc.HTTPInternalServerError(msg))}) kwargs = {'body': body, 'content_type': content_type} raise webob.exc.HTTPInternalServerError(**kwargs) status = action_status.get(action, 200) body = serializer.serialize(result) # NOTE(jkoelker) Comply with RFC2616 section 9.7 if status == 204: content_type = '' body = None return webob.Response(request=request, status=status, content_type=content_type, body=body) return resource
def test_json_with_utf8(self): data = b'{"a": "\xe7\xbd\x91\xe7\xbb\x9c"}' as_dict = {'body': {'a': u'\u7f51\u7edc'}} deserializer = wsgi.JSONDeserializer() self.assertEqual(as_dict, deserializer.deserialize(data))
def Resource(controller, faults=None, deserializers=None, serializers=None, action_status=None): """Represents an API entity resource and the associated serialization and deserialization logic """ default_deserializers = {'application/json': wsgi.JSONDeserializer()} default_serializers = {'application/json': wsgi.JSONDictSerializer()} format_types = {'json': 'application/json'} action_status = action_status or dict(create=201, delete=204) default_deserializers.update(deserializers or {}) default_serializers.update(serializers or {}) deserializers = default_deserializers serializers = default_serializers faults = faults or {} @webob.dec.wsgify(RequestClass=Request) def resource(request): route_args = request.environ.get('wsgiorg.routing_args') if route_args: args = route_args[1].copy() else: args = {} # NOTE(jkoelker) by now the controller is already found, remove # it from the args if it is in the matchdict args.pop('controller', None) fmt = args.pop('format', None) action = args.pop('action', None) content_type = format_types.get(fmt, request.best_match_content_type()) language = request.best_match_language() deserializer = deserializers.get(content_type) serializer = serializers.get(content_type) try: if request.body: args['body'] = deserializer.deserialize(request.body)['body'] # Routes library is dumb and cuts off everything after last dot (.) # as format. At the same time, it doesn't enforce format suffix, # which combined makes it impossible to pass a 'id' with dots # included (the last section after the last dot is lost). This is # important for some API extensions like tags where the id is # really a tag name that can contain special characters. # # To work around the Routes behaviour, we will attach the suffix # back to id if it's not one of supported formats (atm json only). # This of course won't work for the corner case of a tag name that # actually ends with '.json', but there seems to be no better way # to tackle it without breaking API backwards compatibility. if fmt is not None and fmt not in format_types: args['id'] = '.'.join([args['id'], fmt]) revision_number = api_common.check_request_for_revision_constraint( request) if revision_number is not None: request.context.set_transaction_constraint( controller._collection, args['id'], revision_number) method = getattr(controller, action) result = method(request=request, **args) except Exception as e: mapped_exc = api_common.convert_exception_to_http_exc( e, faults, language) if hasattr(mapped_exc, 'code') and 400 <= mapped_exc.code < 500: LOG.info(_LI('%(action)s failed (client error): %(exc)s'), { 'action': action, 'exc': mapped_exc }) else: LOG.exception(_LE('%(action)s failed: %(details)s'), { 'action': action, 'details': utils.extract_exc_details(e), }) raise mapped_exc status = action_status.get(action, 200) body = serializer.serialize(result) # NOTE(jkoelker) Comply with RFC2616 section 9.7 if status == 204: content_type = '' body = None return webob.Response(request=request, status=status, content_type=content_type, body=body) # NOTE(blogan): this is something that is needed for the transition to # pecan. This will allow the pecan code to have a handle on the controller # for an extension so it can reuse the code instead of forcing every # extension to rewrite the code for use with pecan. setattr(resource, 'controller', controller) setattr(resource, 'action_status', action_status) return resource