Fix HEAD request response when request not given to response.
If a middleware (swift3, I'm looking at you), doesn't pass a Request object into the Response constructor, Response._response_iter cannot know to send zero bytes in the body of the HEAD response. This patch fixes this usage of swob by making Response.__call__ helpfully reify self.request from env if it wasn't already set by the Response object's constructor. This fixes a bug in swift3 + swob-enabled-Swift where HEAD requests to swift3 resulted in a response with a body in violation of the relevant RFC and confusing clients. Thanks to kostecky for finding the bug and describing it accurately. Change-Id: I2bdb098052b161e1cddf1e4e482ab4dfafeb18c0
This commit is contained in:
parent
b8626f9667
commit
e2929ec58a
@ -997,6 +997,8 @@ class Response(object):
|
||||
return self.host_url() + self.location
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
if not self.request:
|
||||
self.request = Request(env)
|
||||
self.environ = env
|
||||
app_iter = self._response_iter(self.app_iter, self._body)
|
||||
if 'location' in self.headers:
|
||||
|
@ -462,6 +462,24 @@ class TestResponse(unittest.TestCase):
|
||||
resp.body = u'\N{SNOWMAN}'
|
||||
self.assertEquals(resp.body, u'\N{SNOWMAN}'.encode('utf-8'))
|
||||
|
||||
def test_call_reifies_request_if_necessary(self):
|
||||
"""
|
||||
The actual bug was a HEAD response coming out with a body because the
|
||||
Request object wasn't passed into the Response object's constructor.
|
||||
The Response object's __call__ method should be able to reify a
|
||||
Request object from the env it gets passed.
|
||||
"""
|
||||
def test_app(environ, start_response):
|
||||
start_response('200 OK', [])
|
||||
return ['hi']
|
||||
req = swift.common.swob.Request.blank('/')
|
||||
req.method = 'HEAD'
|
||||
status, headers, app_iter = req.call_application(test_app)
|
||||
resp = swift.common.swob.Response(status=status, headers=dict(headers),
|
||||
app_iter=app_iter)
|
||||
output_iter = resp(req.environ, lambda *_: None)
|
||||
self.assertEquals(list(output_iter), [''])
|
||||
|
||||
def test_location_rewrite(self):
|
||||
def start_response(env, headers):
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user