diff options
author | Markus Zoeller <mzoeller@de.ibm.com> | 2017-04-04 17:23:09 +0200 |
---|---|---|
committer | Markus Zoeller <mzoeller@de.ibm.com> | 2017-04-04 17:26:16 +0200 |
commit | 7db528379ac8bd9a1f2101a73f78f882884825da (patch) | |
tree | d93c109102f741d4dcf92a7bfb57ec0020d812a0 /nova/api | |
parent | 13e51e29a4d733715dd7ea8641008cedf4ad0f78 (diff) | |
download | nova-7db528379ac8bd9a1f2101a73f78f882884825da.tar.gz |
API: accept None as content-length in HTTP requests
The API defines PUT and POST as HTTP methods which need a request body.
It is allowed, that this request body might be of zero length. What was
missing is, that the "content-length" of the request also might be None.
The tempest test cases of servers.test_server_tags.ServerTagsTestJSON
revealed that a PUT with a non-existing body raises a BadRequest exception
because of the missing "content-length".
[tempest.lib.common.rest_client]
Request - Headers:
{'Content-Type': 'application/json', 'Accept': 'application/json',
'X-OpenStack-Nova-API-Version': '2.26', 'X-Auth-Token': '<omitted>'}
Body: None
Response - Headers: {'status': '400', u'content-length': '66',
u'server': 'Apache/2.4.6 (CentOS)
OpenSSL/1.0.1e-fips mod_wsgi/3.4 Python/2.7.5',
u'date': 'Mon, 03 Apr 2017 10:15:12 GMT',
u'x-openstack-nova-api-version': '2.26',
u'x-compute-request-id': 'req-1f8726fc-df20-4592-a214-cff3fa73c8e6',
u'content-type': 'application/json; charset=UTF-8',
content-location': 'https://ctrl:8774/v2.1/servers/<uuid>/tags/mytag',
u'vary': 'OpenStack-API-Version,X-OpenStack-Nova-API-Version',
u'openstack-api-version': 'compute 2.26',
u'connection': 'close'}
Body: {"badRequest":
{"message": "Malformed request body", "code": 400}
}
For some reason this, this seems to only occur on centos7 test nodes,
but not on ubuntu xenial nodes. The root cause is still unclear to me.
I suspect the underlying "webob.Request" object which is used in Nova's
API, but I don't have proof for that.
This change checks for "content-length is None". The logic to determine the
request content was part of a very long method which is hard to test. That's
why I extracted the code paths to a new method. That made the unit test much
easier.
Change I3236648f79f44d2758bb7ab0d64d58b0143f6bdb alters the tempest test
cases which revealed the missing handling of "content-length is None".
Change-Id: Id0b0ab5050a4ec15ab2a0d0dd67fcefe4b1ecb39
Closes-Bug: #1679223
Diffstat (limited to 'nova/api')
-rw-r--r-- | nova/api/openstack/wsgi.py | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index 1144400c34..73d37655c6 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -625,13 +625,7 @@ class Resource(wsgi.Application): # Now, deserialize the request body... try: - contents = {} - if self._should_have_body(request): - # allow empty body with PUT and POST - if request.content_length == 0: - contents = {'body': None} - else: - contents = self.deserialize(body) + contents = self._get_request_content(body, request) except exception.MalformedRequestBody: msg = _("Malformed request body") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) @@ -699,6 +693,16 @@ class Resource(wsgi.Application): return response + def _get_request_content(self, body, request): + contents = {} + if self._should_have_body(request): + # allow empty body with PUT and POST + if request.content_length == 0 or request.content_length is None: + contents = {'body': None} + else: + contents = self.deserialize(body) + return contents + def get_method(self, request, action, content_type, body): meth, extensions = self._get_method(request, action, |