summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorBrian Waldon <brian.waldon@rackspace.com>2011-07-11 13:26:22 -0400
committerBrian Waldon <brian.waldon@rackspace.com>2011-07-11 13:26:22 -0400
commit07b8fc85bb5af2e76a9d970a3ea818aa65dc3b1f (patch)
treee925f19b75b7f07adf017b1b1d408b3047aeb37c /nova
parent6a0b3b8a143e60334dab7ed541caca1eba27c88b (diff)
parentad23d0f354b8698b5314ed2a55e5a4d17abffba0 (diff)
downloadnova-07b8fc85bb5af2e76a9d970a3ea818aa65dc3b1f.tar.gz
nova-07b8fc85bb5af2e76a9d970a3ea818aa65dc3b1f.tar.xz
nova-07b8fc85bb5af2e76a9d970a3ea818aa65dc3b1f.zip
merging parent wsgi-refactor
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/wsgi.py54
-rw-r--r--nova/tests/api/openstack/test_wsgi.py82
2 files changed, 94 insertions, 42 deletions
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index 7a8376722..8eff9e441 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -57,16 +57,26 @@ class Request(webob.Request):
return content_type
-class TextDeserializer(object):
- """Custom request body deserialization based on controller action name."""
+class ActionDispatcher(object):
+ """Maps method name to local methods through action name."""
- def deserialize(self, datastring, action='default'):
- """Find local deserialization method and parse request body."""
+ def dispatch(self, *args, **kwargs):
+ """Find and call local method."""
+ action = kwargs.pop('action', 'default')
action_method = getattr(self, str(action), self.default)
- return action_method(datastring)
+ return action_method(*args, **kwargs)
+
+ def default(self, data):
+ raise NotImplementedError()
+
+
+class TextDeserializer(ActionDispatcher):
+ """Default request body deserialization"""
+
+ def deserialize(self, datastring, action='default'):
+ return self.dispatch(datastring, action=action)
def default(self, datastring):
- """Default deserialization code should live here"""
return {}
@@ -128,8 +138,13 @@ class XMLDeserializer(TextDeserializer):
return {'body': self._from_xml(datastring)}
-class RequestHeadersDeserializer(object):
+class RequestHeadersDeserializer(ActionDispatcher):
+ """Default request headers deserializer"""
+
def deserialize(self, request, action):
+ return self.dispatch(request, action=action)
+
+ def default(self, request):
return {}
@@ -220,20 +235,18 @@ class RequestDeserializer(object):
return args
-class DictSerializer(object):
- """Custom response body serialization based on controller action name."""
+class DictSerializer(ActionDispatcher):
+ """Default request body serialization"""
def serialize(self, data, action='default'):
- """Find local serialization method and encode response body."""
- action_method = getattr(self, str(action), self.default)
- return action_method(data)
+ return self.dispatch(data, action=action)
def default(self, data):
- """Default serialization code should live here"""
- raise NotImplementedError()
+ return ""
class JSONDictSerializer(DictSerializer):
+ """Default JSON request body serialization"""
def default(self, data):
return utils.dumps(data)
@@ -320,8 +333,13 @@ class XMLDictSerializer(DictSerializer):
return result
-class ResponseHeadersSerializer(object):
+class ResponseHeadersSerializer(ActionDispatcher):
+ """Default response headers serialization"""
+
def serialize(self, response, data, action):
+ self.dispatch(response, data, action=action)
+
+ def default(self, response, data):
response.status_int = 200
@@ -409,8 +427,10 @@ class Resource(wsgi.Application):
action_result = self.dispatch(request, action, args)
#TODO(bcwaldon): find a more elegant way to pass through non-dict types
- if type(action_result) is dict:
- response = self.serializer.serialize(action_result, accept, action)
+ if type(action_result) is dict or action_result is None:
+ response = self.serializer.serialize(action_result,
+ accept,
+ action=action)
else:
response = action_result
diff --git a/nova/tests/api/openstack/test_wsgi.py b/nova/tests/api/openstack/test_wsgi.py
index 938637207..5bdda7c7e 100644
--- a/nova/tests/api/openstack/test_wsgi.py
+++ b/nova/tests/api/openstack/test_wsgi.py
@@ -75,24 +75,48 @@ class RequestTest(test.TestCase):
self.assertEqual(result, "application/json")
-class DictSerializerTest(test.TestCase):
+class ActionDispatcherTest(test.TestCase):
def test_dispatch(self):
- serializer = wsgi.DictSerializer()
+ serializer = wsgi.ActionDispatcher()
+ serializer.create = lambda x: 'pants'
+ self.assertEqual(serializer.dispatch({}, action='create'), 'pants')
+
+ def test_dispatch_action_None(self):
+ serializer = wsgi.ActionDispatcher()
serializer.create = lambda x: 'pants'
serializer.default = lambda x: 'trousers'
- self.assertEqual(serializer.serialize({}, 'create'), 'pants')
+ self.assertEqual(serializer.dispatch({}, action=None), 'trousers')
def test_dispatch_default(self):
- serializer = wsgi.DictSerializer()
+ serializer = wsgi.ActionDispatcher()
serializer.create = lambda x: 'pants'
serializer.default = lambda x: 'trousers'
- self.assertEqual(serializer.serialize({}, 'update'), 'trousers')
+ self.assertEqual(serializer.dispatch({}, action='update'), 'trousers')
- def test_dispatch_action_None(self):
+
+class ResponseHeadersSerializerTest(test.TestCase):
+ def test_default(self):
+ serializer = wsgi.ResponseHeadersSerializer()
+ response = webob.Response()
+ serializer.serialize(response, {'v': '123'}, 'asdf')
+ self.assertEqual(response.status_int, 200)
+
+ def test_custom(self):
+ class Serializer(wsgi.ResponseHeadersSerializer):
+ def update(self, response, data):
+ response.status_int = 404
+ response.headers['X-Custom-Header'] = data['v']
+ serializer = Serializer()
+ response = webob.Response()
+ serializer.serialize(response, {'v': '123'}, 'update')
+ self.assertEqual(response.status_int, 404)
+ self.assertEqual(response.headers['X-Custom-Header'], '123')
+
+
+class DictSerializerTest(test.TestCase):
+ def test_dispatch_default(self):
serializer = wsgi.DictSerializer()
- serializer.create = lambda x: 'pants'
- serializer.default = lambda x: 'trousers'
- self.assertEqual(serializer.serialize({}, None), 'trousers')
+ self.assertEqual(serializer.serialize({}, 'update'), '')
class XMLDictSerializerTest(test.TestCase):
@@ -116,23 +140,9 @@ class JSONDictSerializerTest(test.TestCase):
class TextDeserializerTest(test.TestCase):
- def test_dispatch(self):
- deserializer = wsgi.TextDeserializer()
- deserializer.create = lambda x: 'pants'
- deserializer.default = lambda x: 'trousers'
- self.assertEqual(deserializer.deserialize({}, 'create'), 'pants')
-
def test_dispatch_default(self):
deserializer = wsgi.TextDeserializer()
- deserializer.create = lambda x: 'pants'
- deserializer.default = lambda x: 'trousers'
- self.assertEqual(deserializer.deserialize({}, 'update'), 'trousers')
-
- def test_dispatch_action_None(self):
- deserializer = wsgi.TextDeserializer()
- deserializer.create = lambda x: 'pants'
- deserializer.default = lambda x: 'trousers'
- self.assertEqual(deserializer.deserialize({}, None), 'trousers')
+ self.assertEqual(deserializer.deserialize({}, 'update'), {})
class JSONDeserializerTest(test.TestCase):
@@ -189,6 +199,22 @@ class XMLDeserializerTest(test.TestCase):
self.assertEqual(deserializer.deserialize(xml), as_dict)
+class RequestHeadersDeserializerTest(test.TestCase):
+ def test_default(self):
+ deserializer = wsgi.RequestHeadersDeserializer()
+ req = wsgi.Request.blank('/')
+ self.assertEqual(deserializer.deserialize(req, 'asdf'), {})
+
+ def test_custom(self):
+ class Deserializer(wsgi.RequestHeadersDeserializer):
+ def update(self, request):
+ return {'a': request.headers['X-Custom-Header']}
+ deserializer = Deserializer()
+ req = wsgi.Request.blank('/')
+ req.headers['X-Custom-Header'] = 'b'
+ self.assertEqual(deserializer.deserialize(req, 'update'), {'a': 'b'})
+
+
class ResponseSerializerTest(test.TestCase):
def setUp(self):
class JSONSerializer(object):
@@ -199,12 +225,17 @@ class ResponseSerializerTest(test.TestCase):
def serialize(self, data, action='default'):
return 'pew_xml'
+ class HeadersSerializer(object):
+ def serialize(self, response, data, action):
+ response.status_int = 404
+
self.body_serializers = {
'application/json': JSONSerializer(),
'application/XML': XMLSerializer(),
}
- self.serializer = wsgi.ResponseSerializer(self.body_serializers)
+ self.serializer = wsgi.ResponseSerializer(self.body_serializers,
+ HeadersSerializer())
def tearDown(self):
pass
@@ -223,6 +254,7 @@ class ResponseSerializerTest(test.TestCase):
response = self.serializer.serialize({}, 'application/json')
self.assertEqual(response.headers['Content-Type'], 'application/json')
self.assertEqual(response.body, 'pew_json')
+ self.assertEqual(response.status_int, 404)
def test_serialize_response_dict_to_unknown_content_type(self):
self.assertRaises(exception.InvalidContentType,