Fix missing content length of Response

This patch fixes swob.Response to set missing content
length correctly.

When a child class of swob.Response is initialized with
both "body" and "headers" arguments which includes content
length, swob.Response might loose the acutual content length
generated from the body because "headers" will overwrite the
content length property after the body assignment.

It'll cause the difference between headers's content length
and acutual body length. This would affect mainly 3rd party
middleware(s) to make an original response as follows:

req = swob.Request.blank('/')
req.method = 'HEAD'
resp = req.get_response(app)
return HTTPOk(body='Ok', headers=resp.headers)

This patch changes the order of headers updating and then
fixes init() to set correct content length.

Change-Id: Icd8b7cbfe6bbe2c7965175969af299a5eb7a74ef
This commit is contained in:
Kota Tsuyuzaki 2015-01-13 05:34:37 -08:00
parent 8cf9107022
commit 6f21504ccc
2 changed files with 55 additions and 0 deletions

View File

@ -1112,6 +1112,10 @@ class Response(object):
else:
self.environ = {}
if headers:
if self._body and 'Content-Length' in headers:
# If body is not empty, prioritize actual body length over
# content_length in headers
del headers['Content-Length']
self.headers.update(headers)
if self.status_int == 401 and 'www-authenticate' not in self.headers:
self.headers.update({'www-authenticate': self.www_authenticate()})

View File

@ -1419,6 +1419,57 @@ class TestResponse(unittest.TestCase):
'<html><h1>Insufficient Storage</h1><p>There was not enough space '
'to save the resource. Drive: sda1</p></html>')
def test_200_with_body_and_headers(self):
headers = {'Content-Length': '0'}
content = 'foo'
resp = swift.common.swob.HTTPOk(body=content, headers=headers)
self.assertEquals(resp.body, content)
self.assertEquals(resp.content_length, len(content))
def test_init_with_body_headers_app_iter(self):
# body exists but no headers and no app_iter
body = 'ok'
resp = swift.common.swob.Response(body=body)
self.assertEquals(resp.body, body)
self.assertEquals(resp.content_length, len(body))
# body and headers with 0 content_length exist but no app_iter
body = 'ok'
resp = swift.common.swob.Response(
body=body, headers={'Content-Length': '0'})
self.assertEquals(resp.body, body)
self.assertEquals(resp.content_length, len(body))
# body and headers with content_length exist but no app_iter
body = 'ok'
resp = swift.common.swob.Response(
body=body, headers={'Content-Length': '5'})
self.assertEquals(resp.body, body)
self.assertEquals(resp.content_length, len(body))
# body and headers with no content_length exist but no app_iter
body = 'ok'
resp = swift.common.swob.Response(body=body, headers={})
self.assertEquals(resp.body, body)
self.assertEquals(resp.content_length, len(body))
# body, headers with content_length and app_iter exist
resp = swift.common.swob.Response(
body='ok', headers={'Content-Length': '5'}, app_iter=iter([]))
self.assertEquals(resp.content_length, 5)
self.assertEquals(resp.body, '')
# headers with content_length and app_iter exist but no body
resp = swift.common.swob.Response(
headers={'Content-Length': '5'}, app_iter=iter([]))
self.assertEquals(resp.content_length, 5)
self.assertEquals(resp.body, '')
# app_iter exists but no body and headers
resp = swift.common.swob.Response(app_iter=iter([]))
self.assertEquals(resp.content_length, None)
self.assertEquals(resp.body, '')
class TestUTC(unittest.TestCase):
def test_tzname(self):