From 052904ba32f6e6075b023065bff684042c640c6a Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Wed, 30 Jul 2014 10:57:46 +0200 Subject: [PATCH] Don't replace the https handler in the poolmanager In order to keep the support for `--ssl-nocompression` it was decided to overwrite the https HTTPAdapter in `requests` poolmanager. Although this seemed to work correctly, it was causing some issues when using glanceclient from other services that rely on requests and that were also configured to use TLS. THis patch changes implements a different strategy by using `glance+https` as the scheme to use when `no-compression` is requested. Closes-bug: #1350251 Closes-bug: #1347150 Closes-bug: #1362766 Change-Id: Ib25237ba821ee20a561a163b79402d1375ebed0b --- glanceclient/common/http.py | 3 ++- glanceclient/common/https.py | 16 ++++++++++++++-- tests/test_ssl.py | 12 +++++++++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/glanceclient/common/http.py b/glanceclient/common/http.py index fa46d155..0d70f6a6 100644 --- a/glanceclient/common/http.py +++ b/glanceclient/common/http.py @@ -70,7 +70,8 @@ class HTTPClient(object): compression = kwargs.get('ssl_compression', True) if not compression: - self.session.mount("https://", https.HTTPSAdapter()) + self.session.mount("glance+https://", https.HTTPSAdapter()) + self.endpoint = 'glance+' + self.endpoint self.session.verify = (kwargs.get('cacert', None), kwargs.get('insecure', False)) diff --git a/glanceclient/common/https.py b/glanceclient/common/https.py index 4f0e6f5f..6baa6afb 100644 --- a/glanceclient/common/https.py +++ b/glanceclient/common/https.py @@ -50,6 +50,7 @@ except ImportError: from glanceclient import exc +from glanceclient.openstack.common import strutils def to_bytes(s): @@ -72,9 +73,16 @@ class HTTPSAdapter(adapters.HTTPAdapter): def __init__(self, *args, **kwargs): # NOTE(flaper87): This line forces poolmanager to use # glanceclient HTTPSConnection - poolmanager.pool_classes_by_scheme["https"] = HTTPSConnectionPool + classes_by_scheme = poolmanager.pool_classes_by_scheme + classes_by_scheme["glance+https"] = HTTPSConnectionPool super(HTTPSAdapter, self).__init__(*args, **kwargs) + def request_url(self, request, proxies): + # NOTE(flaper87): Make sure the url is encoded, otherwise + # python's standard httplib will fail with a TypeError. + url = super(HTTPSAdapter, self).request_url(request, proxies) + return strutils.safe_encode(url) + def cert_verify(self, conn, url, verify, cert): super(HTTPSAdapter, self).cert_verify(conn, url, verify, cert) conn.ca_certs = verify[0] @@ -93,7 +101,7 @@ class HTTPSConnectionPool(connectionpool.HTTPSConnectionPool): be used just when the user sets --no-ssl-compression. """ - scheme = 'https' + scheme = 'glance+https' def _new_conn(self): self.num_connections += 1 @@ -150,6 +158,10 @@ class VerifiedHTTPSConnection(HTTPSConnection): self.cert_file = cert_file self.timeout = timeout self.insecure = insecure + # NOTE(flaper87): `is_verified` is needed for + # requests' urllib3. If insecure is True then + # the request is not `verified`, hence `not insecure` + self.is_verified = not insecure self.ssl_compression = ssl_compression self.cacert = None if cacert is None else str(cacert) self.set_context() diff --git a/tests/test_ssl.py b/tests/test_ssl.py index ecbccfa6..013d18fb 100644 --- a/tests/test_ssl.py +++ b/tests/test_ssl.py @@ -39,12 +39,22 @@ class TestRequestsIntegration(testtools.TestCase): adapter = client.session.adapters.get("https://") self.assertFalse(isinstance(adapter, https.HTTPSAdapter)) + adapter = client.session.adapters.get("glance+https://") + self.assertFalse(isinstance(adapter, https.HTTPSAdapter)) + + def test_custom_https_adapter(self): client = http.HTTPClient("https://localhost", ssl_compression=False) + self.assertNotEqual(https.HTTPSConnectionPool, + poolmanager.pool_classes_by_scheme["https"]) + self.assertEqual(https.HTTPSConnectionPool, - poolmanager.pool_classes_by_scheme["https"]) + poolmanager.pool_classes_by_scheme["glance+https"]) adapter = client.session.adapters.get("https://") + self.assertFalse(isinstance(adapter, https.HTTPSAdapter)) + + adapter = client.session.adapters.get("glance+https://") self.assertTrue(isinstance(adapter, https.HTTPSAdapter))