Merge lp:~rackspace-titan/nova/lp795029 into lp:~hudson-openstack/nova/trunk

Proposed by Alex Meade
Status: Merged
Approved by: Brian Waldon
Approved revision: 1181
Merged at revision: 1181
Proposed branch: lp:~rackspace-titan/nova/lp795029
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 112 lines (+43/-3)
3 files modified
nova/api/openstack/wsgi.py (+18/-3)
nova/exception.py (+4/-0)
nova/tests/api/openstack/test_api.py (+21/-0)
To merge this branch: bzr merge lp:~rackspace-titan/nova/lp795029
Reviewer Review Type Date Requested Status
Ed Leafe (community) Approve
Brian Waldon (community) Approve
Review via email: mp+64558@code.launchpad.net

Description of the change

Changed requests with malformed bodies to return a HTTP 400 Bad Request instead of a HTTP 500 error.

To post a comment you must log in.
Revision history for this message
Brian Waldon (bcwaldon) wrote :

This looks great, Alex. Could you actually wrap the 400 you raise with faults.Fault()? This will get us proper response formats. You can import faults in nova/api/openstack/wsgi.py

review: Needs Fixing
Revision history for this message
Brian Waldon (bcwaldon) wrote :

23, 38: You need to give these exceptions the proper keyword arguments. Looks like you defined MalformedRequestBody to take 'reason'.

47: How about we be a bit more specific and tell the user it was a "Malformed request body", not just a "Malformed request."

Revision history for this message
Ed Leafe (ed-leafe) wrote :

Adding to Brian's comment: when you raise the new exception, you need to pass the argument as a keyword; e.g.:
    raise exception.MalformedRequestBody(reason=_("malformed JSON in request body"))

Line 40 also has a capitalization inconsistency: 'Body' should be lowercase 'body'.

Line 66 can be more simply written as:
    message = _("Malformed message body: %(reason)s)"

review: Needs Fixing
Revision history for this message
Ed Leafe (ed-leafe) wrote :

Changes look good.

review: Approve
Revision history for this message
Brian Waldon (bcwaldon) wrote :

Awesome.

Awesome to the max.

review: Approve
Revision history for this message
OpenStack Infra (hudson-openstack) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Revision history for this message
Ed Leafe (ed-leafe) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'nova/api/openstack/wsgi.py'
--- nova/api/openstack/wsgi.py 2011-06-13 20:00:14 +0000
+++ nova/api/openstack/wsgi.py 2011-06-14 17:29:59 +0000
@@ -2,8 +2,10 @@
2import json2import json
3import webob3import webob
4from xml.dom import minidom4from xml.dom import minidom
5from xml.parsers.expat import ExpatError
56
6from nova import exception7from nova import exception
8import faults
7from nova import log as logging9from nova import log as logging
8from nova import utils10from nova import utils
9from nova import wsgi11from nova import wsgi
@@ -71,7 +73,11 @@
71class JSONDeserializer(TextDeserializer):73class JSONDeserializer(TextDeserializer):
7274
73 def default(self, datastring):75 def default(self, datastring):
74 return utils.loads(datastring)76 try:
77 return utils.loads(datastring)
78 except ValueError:
79 raise exception.MalformedRequestBody(
80 reason=_("malformed JSON in request body"))
7581
7682
77class XMLDeserializer(TextDeserializer):83class XMLDeserializer(TextDeserializer):
@@ -86,8 +92,13 @@
8692
87 def default(self, datastring):93 def default(self, datastring):
88 plurals = set(self.metadata.get('plurals', {}))94 plurals = set(self.metadata.get('plurals', {}))
89 node = minidom.parseString(datastring).childNodes[0]95
90 return {node.nodeName: self._from_xml_node(node, plurals)}96 try:
97 node = minidom.parseString(datastring).childNodes[0]
98 return {node.nodeName: self._from_xml_node(node, plurals)}
99 except ExpatError:
100 raise exception.MalformedRequestBody(
101 reason=_("malformed XML in request body"))
91102
92 def _from_xml_node(self, node, listnames):103 def _from_xml_node(self, node, listnames):
93 """Convert a minidom node to a simple Python type.104 """Convert a minidom node to a simple Python type.
@@ -353,6 +364,10 @@
353 request)364 request)
354 except exception.InvalidContentType:365 except exception.InvalidContentType:
355 return webob.exc.HTTPBadRequest(_("Unsupported Content-Type"))366 return webob.exc.HTTPBadRequest(_("Unsupported Content-Type"))
367 except exception.MalformedRequestBody:
368 explanation = _("Malformed request body")
369 return faults.Fault(webob.exc.HTTPBadRequest(
370 explanation=explanation))
356371
357 action_result = self.dispatch(request, action, action_args)372 action_result = self.dispatch(request, action, action_args)
358373
359374
=== modified file 'nova/exception.py'
--- nova/exception.py 2011-06-11 01:31:10 +0000
+++ nova/exception.py 2011-06-14 17:29:59 +0000
@@ -585,3 +585,7 @@
585585
586class MigrationError(NovaException):586class MigrationError(NovaException):
587 message = _("Migration error") + ": %(reason)s"587 message = _("Migration error") + ": %(reason)s"
588
589
590class MalformedRequestBody(NovaException):
591 message = _("Malformed message body: %(reason)s")
588592
=== modified file 'nova/tests/api/openstack/test_api.py'
--- nova/tests/api/openstack/test_api.py 2011-04-07 18:55:42 +0000
+++ nova/tests/api/openstack/test_api.py 2011-06-14 17:29:59 +0000
@@ -15,6 +15,8 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18import json
19
18import webob.exc20import webob.exc
19import webob.dec21import webob.dec
2022
@@ -23,6 +25,7 @@
23from nova import test25from nova import test
24from nova.api import openstack26from nova.api import openstack
25from nova.api.openstack import faults27from nova.api.openstack import faults
28from nova.tests.api.openstack import fakes
2629
2730
28class APITest(test.TestCase):31class APITest(test.TestCase):
@@ -31,6 +34,24 @@
31 # simpler version of the app than fakes.wsgi_app34 # simpler version of the app than fakes.wsgi_app
32 return openstack.FaultWrapper(inner_app)35 return openstack.FaultWrapper(inner_app)
3336
37 def test_malformed_json(self):
38 req = webob.Request.blank('/')
39 req.method = 'POST'
40 req.body = '{'
41 req.headers["content-type"] = "application/json"
42
43 res = req.get_response(fakes.wsgi_app())
44 self.assertEqual(res.status_int, 400)
45
46 def test_malformed_xml(self):
47 req = webob.Request.blank('/')
48 req.method = 'POST'
49 req.body = '<hi im not xml>'
50 req.headers["content-type"] = "application/xml"
51
52 res = req.get_response(fakes.wsgi_app())
53 self.assertEqual(res.status_int, 400)
54
34 def test_exceptions_are_converted_to_faults(self):55 def test_exceptions_are_converted_to_faults(self):
3556
36 @webob.dec.wsgify57 @webob.dec.wsgify