Allow to create a rest_client not following redirects
Some tests need to verify that the first response from an API is indeed
a redirect, this can not be done if the client automatically follows
redirects. Introduce a parameter that allows consumers to disable the
default behaviour, so that they can see the 301 response instead.
Change-Id: I366fa8d1971cd7502a1cd985f5ee6ad5e1ecb216
Closes-Bug: 1616892
diff --git a/releasenotes/notes/add-redirect-param-bea1f6fbce629c70.yaml b/releasenotes/notes/add-redirect-param-bea1f6fbce629c70.yaml
new file mode 100644
index 0000000..f245dcb
--- /dev/null
+++ b/releasenotes/notes/add-redirect-param-bea1f6fbce629c70.yaml
@@ -0,0 +1,16 @@
+---
+features:
+ - |
+ A new parameter ``follow_redirects`` has been added to the class
+ ``RestClient``, which is passed through to ``ClosingHttp`` or
+ ``ClosingProxyHttp`` respectively. The default value is ``True``
+ which corresponds to the previous behaviour of following up to five
+ redirections before returning a response. Setting
+ ``follow_redirects = False`` allows to disable this behaviour, so
+ that any redirect that is received is directly returned to the caller.
+ This allows tests to verify that an API is responding with a redirect.
+fixes:
+ - |
+ [`bug 1616892 <https://bugs.launchpad.net/tempest/+bug/1616892>`_]
+ Tempest now allows tests to verify that an API responds with a
+ redirect.
diff --git a/tempest/lib/common/http.py b/tempest/lib/common/http.py
index 738c37f..8c1a802 100644
--- a/tempest/lib/common/http.py
+++ b/tempest/lib/common/http.py
@@ -19,7 +19,8 @@
class ClosingProxyHttp(urllib3.ProxyManager):
def __init__(self, proxy_url, disable_ssl_certificate_validation=False,
- ca_certs=None, timeout=None):
+ ca_certs=None, timeout=None, follow_redirects=True):
+ self.follow_redirects = follow_redirects
kwargs = {}
if disable_ssl_certificate_validation:
@@ -50,9 +51,14 @@
new_headers = dict(original_headers, connection='close')
new_kwargs = dict(kwargs, headers=new_headers)
- # Follow up to 5 redirections. Don't raise an exception if
- # it's exceeded but return the HTTP 3XX response instead.
- retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
+ if self.follow_redirects:
+ # Follow up to 5 redirections. Don't raise an exception if
+ # it's exceeded but return the HTTP 3XX response instead.
+ retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
+ else:
+ # Do not follow redirections. Don't raise an exception if
+ # a redirect is found, but return the HTTP 3XX response instead.
+ retry = urllib3.util.Retry(redirect=False)
r = super(ClosingProxyHttp, self).request(method, url, retries=retry,
*args, **new_kwargs)
return Response(r), r.data
@@ -60,7 +66,8 @@
class ClosingHttp(urllib3.poolmanager.PoolManager):
def __init__(self, disable_ssl_certificate_validation=False,
- ca_certs=None, timeout=None):
+ ca_certs=None, timeout=None, follow_redirects=True):
+ self.follow_redirects = follow_redirects
kwargs = {}
if disable_ssl_certificate_validation:
@@ -93,9 +100,14 @@
new_headers = dict(original_headers, connection='close')
new_kwargs = dict(kwargs, headers=new_headers)
- # Follow up to 5 redirections. Don't raise an exception if
- # it's exceeded but return the HTTP 3XX response instead.
- retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
+ if self.follow_redirects:
+ # Follow up to 5 redirections. Don't raise an exception if
+ # it's exceeded but return the HTTP 3XX response instead.
+ retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
+ else:
+ # Do not follow redirections. Don't raise an exception if
+ # a redirect is found, but return the HTTP 3XX response instead.
+ retry = urllib3.util.Retry(redirect=False)
r = super(ClosingHttp, self).request(method, url, retries=retry,
*args, **new_kwargs)
return Response(r), r.data
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 22276d4..fd1c91e 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -70,6 +70,7 @@
:param str http_timeout: Timeout in seconds to wait for the http request to
return
:param str proxy_url: http proxy url to use.
+ :param bool follow_redirects: Set to false to stop following redirects.
"""
# The version of the API this client implements
@@ -82,7 +83,7 @@
build_interval=1, build_timeout=60,
disable_ssl_certificate_validation=False, ca_certs=None,
trace_requests='', name=None, http_timeout=None,
- proxy_url=None):
+ proxy_url=None, follow_redirects=True):
self.auth_provider = auth_provider
self.service = service
self.region = region
@@ -107,11 +108,11 @@
self.http_obj = http.ClosingProxyHttp(
proxy_url,
disable_ssl_certificate_validation=dscv, ca_certs=ca_certs,
- timeout=http_timeout)
+ timeout=http_timeout, follow_redirects=follow_redirects)
else:
self.http_obj = http.ClosingHttp(
disable_ssl_certificate_validation=dscv, ca_certs=ca_certs,
- timeout=http_timeout)
+ timeout=http_timeout, follow_redirects=follow_redirects)
def get_headers(self, accept_type=None, send_type=None):
"""Return the default headers which will be used with outgoing requests
diff --git a/tempest/tests/lib/common/test_http.py b/tempest/tests/lib/common/test_http.py
index 02436e0..336ef4a 100644
--- a/tempest/tests/lib/common/test_http.py
+++ b/tempest/tests/lib/common/test_http.py
@@ -167,3 +167,30 @@
'%s://%s:%i' % (proxy.scheme,
proxy.host,
proxy.port))
+
+
+class TestClosingHttpRedirects(base.TestCase):
+ def setUp(self):
+ super(TestClosingHttpRedirects, self).setUp()
+
+ def test_redirect_default(self):
+ connection = http.ClosingHttp()
+ self.assertTrue(connection.follow_redirects)
+
+ def test_redirect_off(self):
+ connection = http.ClosingHttp(follow_redirects=False)
+ self.assertFalse(connection.follow_redirects)
+
+
+class TestClosingProxyHttpRedirects(base.TestCase):
+ def setUp(self):
+ super(TestClosingProxyHttpRedirects, self).setUp()
+
+ def test_redirect_default(self):
+ connection = http.ClosingProxyHttp(proxy_url=PROXY_URL)
+ self.assertTrue(connection.follow_redirects)
+
+ def test_redirect_off(self):
+ connection = http.ClosingProxyHttp(follow_redirects=False,
+ proxy_url=PROXY_URL)
+ self.assertFalse(connection.follow_redirects)