diff options
author | Soren Hansen <soren.hansen@rackspace.com> | 2010-09-29 13:29:45 +0200 |
---|---|---|
committer | Soren Hansen <soren.hansen@rackspace.com> | 2010-09-29 13:29:45 +0200 |
commit | c43fb8325eb068e970df02ec99d02f37de38ecc4 (patch) | |
tree | b4ecce6394cdb4ceb8fb382cb12045870177bb9b /nova/wsgi.py | |
parent | e609dd8620796f4eadefcff6130dfeae06b97ef4 (diff) | |
parent | 43ce84290964b433fd9d9898772d29bffc385dd8 (diff) | |
download | nova-c43fb8325eb068e970df02ec99d02f37de38ecc4.tar.gz nova-c43fb8325eb068e970df02ec99d02f37de38ecc4.tar.xz nova-c43fb8325eb068e970df02ec99d02f37de38ecc4.zip |
Merge trunk.
Diffstat (limited to 'nova/wsgi.py')
-rw-r--r-- | nova/wsgi.py | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/nova/wsgi.py b/nova/wsgi.py index 8a4e2a9f4..da9374542 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -21,14 +21,17 @@ Utility methods for working with WSGI servers """ +import json import logging import sys +from xml.dom import minidom import eventlet import eventlet.wsgi eventlet.patcher.monkey_patch(all=False, socket=True) import routes import routes.middleware +import webob import webob.dec import webob.exc @@ -230,7 +233,7 @@ class Controller(object): class Serializer(object): """ - Serializes a dictionary to a Content Type specified by a WSGI environment. + Serializes and deserializes dictionaries to certain MIME types. """ def __init__(self, environ, metadata=None): @@ -239,31 +242,74 @@ class Serializer(object): 'metadata' is an optional dict mapping MIME types to information needed to serialize a dictionary to that type. """ - self.environ = environ self.metadata = metadata or {} - self._methods = { - 'application/json': self._to_json, - 'application/xml': self._to_xml} + req = webob.Request(environ) + suffix = req.path_info.split('.')[-1].lower() + if suffix == 'json': + self.handler = self._to_json + elif suffix == 'xml': + self.handler = self._to_xml + elif 'application/json' in req.accept: + self.handler = self._to_json + elif 'application/xml' in req.accept: + self.handler = self._to_xml + else: + self.handler = self._to_json # default def to_content_type(self, data): """ - Serialize a dictionary into a string. The format of the string - will be decided based on the Content Type requested in self.environ: - by Accept: header, or by URL suffix. + Serialize a dictionary into a string. + + The format of the string will be decided based on the Content Type + requested in self.environ: by Accept: header, or by URL suffix. + """ + return self.handler(data) + + def deserialize(self, datastring): + """ + Deserialize a string to a dictionary. + + The string must be in the format of a supported MIME type. """ - mimetype = 'application/xml' - # TODO(gundlach): determine mimetype from request - return self._methods.get(mimetype, repr)(data) + datastring = datastring.strip() + is_xml = (datastring[0] == '<') + if not is_xml: + return json.loads(datastring) + return self._from_xml(datastring) + + def _from_xml(self, datastring): + xmldata = self.metadata.get('application/xml', {}) + plurals = set(xmldata.get('plurals', {})) + node = minidom.parseString(datastring).childNodes[0] + return {node.nodeName: self._from_xml_node(node, plurals)} + + def _from_xml_node(self, node, listnames): + """ + Convert a minidom node to a simple Python type. + + listnames is a collection of names of XML nodes whose subnodes should + be considered list items. + """ + if len(node.childNodes) == 1 and node.childNodes[0].nodeType == 3: + return node.childNodes[0].nodeValue + elif node.nodeName in listnames: + return [self._from_xml_node(n, listnames) for n in node.childNodes] + else: + result = dict() + for attr in node.attributes.keys(): + result[attr] = node.attributes[attr].nodeValue + for child in node.childNodes: + if child.nodeType != node.TEXT_NODE: + result[child.nodeName] = self._from_xml_node(child, listnames) + return result def _to_json(self, data): - import json return json.dumps(data) def _to_xml(self, data): metadata = self.metadata.get('application/xml', {}) # We expect data to contain a single key which is the XML root. root_key = data.keys()[0] - from xml.dom import minidom doc = minidom.Document() node = self._to_xml_node(doc, metadata, root_key, data[root_key]) return node.toprettyxml(indent=' ') |