Merge "Allow redirects to use location from response"
This commit is contained in:
@@ -201,10 +201,14 @@ class HTTPClient(object):
|
||||
# See issue: https://github.com/kennethreitz/requests/issues/1704
|
||||
allow_redirects = False
|
||||
|
||||
# Use fully qualified URL from response header for redirects
|
||||
if not parse.urlparse(url).netloc:
|
||||
url = self.endpoint_url + url
|
||||
|
||||
try:
|
||||
resp = requests.request(
|
||||
method,
|
||||
self.endpoint_url + url,
|
||||
url,
|
||||
allow_redirects=allow_redirects,
|
||||
**kwargs)
|
||||
except socket.gaierror as e:
|
||||
@@ -231,23 +235,15 @@ class HTTPClient(object):
|
||||
# unless caller specified redirect=False
|
||||
if redirect:
|
||||
location = resp.headers.get('location')
|
||||
path = self.strip_endpoint(location)
|
||||
resp = self._http_request(path, method, **kwargs)
|
||||
if not location:
|
||||
message = _("Location not returned with redirect")
|
||||
raise exc.InvalidEndpoint(message=message)
|
||||
resp = self._http_request(location, method, **kwargs)
|
||||
elif resp.status_code == 300:
|
||||
raise exc.from_response(resp)
|
||||
|
||||
return resp
|
||||
|
||||
def strip_endpoint(self, location):
|
||||
if location is None:
|
||||
message = _("Location not returned with 302")
|
||||
raise exc.InvalidEndpoint(message=message)
|
||||
elif location.lower().startswith(self.endpoint.lower()):
|
||||
return location[len(self.endpoint):]
|
||||
else:
|
||||
message = _("Prohibited endpoint redirect %s") % location
|
||||
raise exc.InvalidEndpoint(message=message)
|
||||
|
||||
def credentials_headers(self):
|
||||
creds = {}
|
||||
# NOTE(dhu): (shardy) When deferred_auth_method=password, Heat
|
||||
|
||||
@@ -421,7 +421,7 @@ class HttpClientTest(testtools.TestCase):
|
||||
{'location': 'http://example.com:8004/foo/bar'},
|
||||
''))
|
||||
mock_conn = http.requests.request(
|
||||
'PUT', 'http://EXAMPLE.com:8004/foo/bar',
|
||||
'PUT', 'http://example.com:8004/foo/bar',
|
||||
allow_redirects=False,
|
||||
headers={'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
@@ -439,23 +439,6 @@ class HttpClientTest(testtools.TestCase):
|
||||
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def test_http_manual_redirect_prohibited(self):
|
||||
mock_conn = http.requests.request(
|
||||
'DELETE', 'http://example.com:8004/foo',
|
||||
allow_redirects=False,
|
||||
headers={'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': 'python-heatclient'})
|
||||
mock_conn.AndReturn(
|
||||
fakes.FakeHTTPResponse(
|
||||
302, 'Found',
|
||||
{'location': 'http://example.com:8004/'},
|
||||
''))
|
||||
self.m.ReplayAll()
|
||||
client = http.HTTPClient('http://example.com:8004/foo')
|
||||
self.assertRaises(exc.InvalidEndpoint,
|
||||
client.json_request, 'DELETE', '')
|
||||
|
||||
def test_http_manual_redirect_error_without_location(self):
|
||||
mock_conn = http.requests.request(
|
||||
'DELETE', 'http://example.com:8004/foo',
|
||||
|
||||
@@ -17,6 +17,8 @@ from heatclient.common import utils
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from heatclient import exc
|
||||
from heatclient.openstack.common._i18n import _
|
||||
from heatclient.openstack.common.apiclient import base
|
||||
|
||||
|
||||
@@ -106,8 +108,10 @@ class StackChildManager(base.BaseManager):
|
||||
# redirected stacks:show, so pass redirect=False
|
||||
resp = self.client.get('/stacks/%s' % stack_id, redirect=False)
|
||||
location = resp.headers.get('location')
|
||||
path = self.client.strip_endpoint(location)
|
||||
return path[len('/stacks/'):]
|
||||
if not location:
|
||||
message = _("Location not returned with redirect")
|
||||
raise exc.InvalidEndpoint(message=message)
|
||||
return location.split('/stacks/', 1)[1]
|
||||
|
||||
|
||||
class StackManager(StackChildManager):
|
||||
|
||||
Reference in New Issue
Block a user