From 78704010cc4c3b5c2bd050ee846323506ad3ed5b Mon Sep 17 00:00:00 2001 From: David Goetz Date: Wed, 22 Jan 2014 13:03:51 -0800 Subject: [PATCH] Add flag to stop swob from always using absolute location. This is a backport of commit 89deaf5f3cb062cc2c2d7d7d365e84ec2e41a511 This is needed for SOS (along with patch https://github.com/dpgoetz/sos/pull/37) to work with swift 1.12 . By spec you should always use the absolute location but this causes a problem with staticweb over a cdn using a cname. Basically you want to be able to forward the browser to a relative location instead of whatever full url the proxy server thinks you are using. Change-Id: I28dcbd779d2aa4a6e636c956b058670b8e4b2fd7 --- doc/source/misc.rst | 11 ++++++++++- swift/common/swob.py | 22 +++++++++++++++++++++- test/unit/common/test_swob.py | 13 +++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/doc/source/misc.rst b/doc/source/misc.rst index 4e201f2134..c046534fc7 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -33,6 +33,16 @@ Utils :members: :show-inheritance: +.. _swob: + +Swob +==== + +.. automodule:: swift.common.swob + :members: + :show-inheritance: + :special-members: __call__ + .. _common_tempauth: TempAuth @@ -51,7 +61,6 @@ KeystoneAuth :members: :show-inheritance: - ACLs ==== diff --git a/swift/common/swob.py b/swift/common/swob.py index 8ee1ead450..9687eeb8de 100644 --- a/swift/common/swob.py +++ b/swift/common/swob.py @@ -1186,11 +1186,31 @@ class Response(object): return self.status_int // 100 == 2 def __call__(self, env, start_response): + """ + Respond to the WSGI request. + + .. warning:: + + This will translate any relative Location header value to an + absolute URL using the WSGI environment's HOST_URL as a + prefix, as RFC 2616 specifies. + + However, it is quite common to use relative redirects, + especially when it is difficult to know the exact HOST_URL + the browser would have used when behind several CNAMEs, CDN + services, etc. All modern browsers support relative + redirects. + + To skip over RFC enforcement of the Location header value, + you may set ``env['swift.leave_relative_location'] = True`` + in the WSGI environment. + """ 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: + if 'location' in self.headers and \ + not env.get('swift.leave_relative_location'): self.location = self.absolute_location() start_response(self.status, self.headers.items()) return app_iter diff --git a/test/unit/common/test_swob.py b/test/unit/common/test_swob.py index c740b435a9..c0de63d045 100644 --- a/test/unit/common/test_swob.py +++ b/test/unit/common/test_swob.py @@ -1034,6 +1034,19 @@ class TestResponse(unittest.TestCase): ''.join(resp(req.environ, start_response)) self.assertEquals(resp.location, 'http://www.google.com/') + def test_location_no_rewrite_when_told_not_to(self): + def start_response(env, headers): + pass + req = swift.common.swob.Request.blank( + '/', environ={'SERVER_NAME': 'local', 'SERVER_PORT': 81, + 'swift.leave_relative_location': True}) + del req.environ['HTTP_HOST'] + resp = self._get_response() + resp.location = '/something' + # read response + ''.join(resp(req.environ, start_response)) + self.assertEquals(resp.location, '/something') + def test_app_iter(self): def start_response(env, headers): pass