def test_json_with_unicode(self): input_dict = dict(servers=dict(a=(2, u'\u7f51\u7edc'))) expected_json = '{"servers":{"a":[2,"\\u7f51\\u7edc"]}}' serializer = wsgi.JSONDictSerializer() result = serializer.serialize(input_dict) result = result.replace('\n', '').replace(' ', '') self.assertEqual(result, expected_json)
def test_json(self): input_dict = dict(servers=dict(a=(2, 3))) expected_json = '{"servers":{"a":[2,3]}}' serializer = wsgi.JSONDictSerializer() result = serializer.serialize(input_dict) result = result.replace('\n', '').replace(' ', '') self.assertEqual(result, expected_json)
def test_json_with_utf8(self): input_dict = dict(servers=dict(a=(2, '\xe7\xbd\x91\xe7\xbb\x9c'))) expected_json = '{"servers":{"a":[2,"\\u7f51\\u7edc"]}}' serializer = wsgi.JSONDictSerializer() result = serializer.serialize(input_dict) result = result.replace('\n', '').replace(' ', '') self.assertEqual(expected_json, result)
def convert_exception_to_http_exc(e, faults, language): serializer = wsgi.JSONDictSerializer() e = translate(e, language) body = serializer.serialize( {'TackerError': get_exception_data(e)}) kwargs = {'body': body, 'content_type': 'application/json'} if isinstance(e, exc.HTTPException): # already an HTTP error, just update with content type and body e.body = body e.content_type = kwargs['content_type'] return e if isinstance(e, (exceptions.TackerException, netaddr.AddrFormatError, oslo_policy.PolicyNotAuthorized)): for fault in faults: if isinstance(e, fault): mapped_exc = faults[fault] break else: mapped_exc = exc.HTTPInternalServerError return mapped_exc(**kwargs) if isinstance(e, NotImplementedError): # 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. kwargs['body'] = serializer.serialize( {'NotImplementedError': get_exception_data(e)}) return exc.HTTPNotImplemented(**kwargs) # NOTE(jkoelker) Everything else is 500 # Do not expose details of 500 error to clients. msg = _('Request Failed: internal server error while ' 'processing your request.') msg = translate(msg, language) kwargs['body'] = serializer.serialize( {'TackerError': get_exception_data(exc.HTTPInternalServerError(msg))}) return exc.HTTPInternalServerError(**kwargs)
def Resource(controller, faults=None, deserializers=None, serializers=None): """API entity resource. 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.TackerException, netaddr.AddrFormatError) 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(_('%(action)s failed (client error): %(exc)s'), {'action': action, 'exc': e}) else: LOG.exception(_('%s failed'), action) e = translate(e, language) # following structure is expected by python-tackerclient err_data = {'type': e.__class__.__name__, 'message': e, 'detail': ''} body = serializer.serialize({'TackerError': err_data}) kwargs = {'body': body, 'content_type': content_type} raise mapped_exc(**kwargs) except webob.exc.HTTPException as e: type_, value, tb = sys.exc_info() LOG.exception(_('%s failed'), action) translate(e, language) value.body = serializer.serialize({'TackerError': 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': e.message}) kwargs = {'body': body, 'content_type': content_type} raise webob.exc.HTTPNotImplemented(**kwargs) except Exception: # NOTE(jkoelker) Everything else is 500 LOG.exception(_('%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({'TackerError': 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 Resource(controller, faults=None, deserializers=None, serializers=None): """API entity resource. 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 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('%(action)s failed (client error): %(exc)s', { 'action': action, 'exc': mapped_exc }) else: LOG.exception('%(action)s failed: %(details)s', { 'action': action, 'details': 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) return resource