From 18d3df78e8cc7ae498ba411fea155a227cb91642 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Wed, 26 Jul 2017 20:37:13 -0400 Subject: [PATCH 01/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client.py | 28 +++++++++++++++++++++++++++- acme/acme/client_test.py | 24 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index fa903f0e686..f781f011b06 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -11,6 +11,7 @@ from six.moves import http_client # pylint: disable=import-error import OpenSSL +import re import requests import sys @@ -599,6 +600,7 @@ def _check_response(cls, response, content_type=None): return response def _send_request(self, method, url, *args, **kwargs): + # pylint: disable=too-many-locals """Send HTTP request. Makes sure that `verify_ssl` is respected. Logs request and @@ -624,7 +626,31 @@ def _send_request(self, method, url, *args, **kwargs): kwargs.setdefault('headers', {}) kwargs['headers'].setdefault('User-Agent', self.user_agent) kwargs.setdefault('timeout', self._default_timeout) - response = self.session.request(method, url, *args, **kwargs) + try: + response = self.session.request(method, url, *args, **kwargs) + except requests.exceptions.RequestException as e: + # pylint: disable=pointless-string-statement + """Requests response parsing + + The requests library emits exceptions with a lot of extra text. + We parse them with a regexp to raise a more readable exceptions. + + Example: + HTTPSConnectionPool(host='acme-v01.api.letsencrypt.org', + port=443): Max retries exceeded with url: /directory + (Caused by NewConnectionError(' + : Failed to establish a new connection: + [Errno 65] No route to host',))""" + + err_regex = r".*host='(\S*)'.*url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)" + m = re.match(err_regex, str(e)) + if m is None: + raise # pragma: no cover + else: + host, path, err_no, err_msg = m.groups() + raise ValueError("Requesting {0}{1}: {2}{3}".format(host, path, err_no, err_msg)) + # If content is DER, log the base64 of it instead of raw bytes, to keep # binary data out of the logs. if response.headers.get("Content-Type") == DER_CONTENT_TYPE: diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 54652b46c1b..c800f476cac 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -7,6 +7,7 @@ import mock import requests +import sys from acme import challenges from acme import errors @@ -621,6 +622,29 @@ def test_requests_error_passthrough(self, mock_requests): self.assertRaises(requests.exceptions.RequestException, self.net._send_request, 'GET', 'uri') + def test_urllib_error(self): + # Using a connection error to test a properly formatted error message + try: + # pylint: disable=protected-access + self.net._send_request('GET', "http://localhost:19123/nonexistent.txt") + + # Python 2 + except ValueError as y: + if "linux" in sys.platform: + self.assertEqual("Requesting localhost/nonexistent: " + "[Errno 111] Connection refused", str(y)) + else: #pragma: no cover + self.assertEqual("Requesting localhost/nonexistent: " + "[Errno 61] Connection refused", str(y)) + + # Python 3 + except requests.exceptions.ConnectionError as z: #pragma: no cover + if "linux" in sys.platform: + self.assertEqual("('Connection aborted.', " + "error(111, 'Connection refused'))", str(z)) + else: #pragma: no cover + self.assertEqual("('Connection aborted.', " + "error(61, 'Connection refused'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From 1e71ff537733d701688117fce0b92d3393018934 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Wed, 2 Aug 2017 22:59:27 -0400 Subject: [PATCH 02/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index f781f011b06..67a4079fda1 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -643,7 +643,9 @@ def _send_request(self, method, url, *args, **kwargs): object at 0x108356c50>: Failed to establish a new connection: [Errno 65] No route to host',))""" - err_regex = r".*host='(\S*)'.*url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)" + print e.message + # pylint: disable=line-too-long + err_regex = r".*host='(\S*)'.*Max retries exceeded with url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)" m = re.match(err_regex, str(e)) if m is None: raise # pragma: no cover From 959d72feb035dd49efc32f8f39f92e79ea32b2c3 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sat, 5 Aug 2017 10:16:47 -0400 Subject: [PATCH 03/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client.py | 2 +- acme/acme/client_test.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index 67a4079fda1..7316066da21 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -651,7 +651,7 @@ def _send_request(self, method, url, *args, **kwargs): raise # pragma: no cover else: host, path, err_no, err_msg = m.groups() - raise ValueError("Requesting {0}{1}: {2}{3}".format(host, path, err_no, err_msg)) + raise ValueError("Requesting {0}{1}: {2}".format(host, path, err_msg)) # If content is DER, log the base64 of it instead of raw bytes, to keep # binary data out of the logs. diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index c800f476cac..1c6b4a77ce1 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -632,19 +632,19 @@ def test_urllib_error(self): except ValueError as y: if "linux" in sys.platform: self.assertEqual("Requesting localhost/nonexistent: " - "[Errno 111] Connection refused", str(y)) + "Connection refused", str(y)) else: #pragma: no cover self.assertEqual("Requesting localhost/nonexistent: " - "[Errno 61] Connection refused", str(y)) + "Connection refused", str(y)) # Python 3 except requests.exceptions.ConnectionError as z: #pragma: no cover if "linux" in sys.platform: self.assertEqual("('Connection aborted.', " - "error(111, 'Connection refused'))", str(z)) + "error('Connection refused'))", str(z)) else: #pragma: no cover self.assertEqual("('Connection aborted.', " - "error(61, 'Connection refused'))", str(z)) + "error('Connection refused'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From 3cc94798b6452f652b898916f5b710293e44f6b4 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sat, 5 Aug 2017 10:26:01 -0400 Subject: [PATCH 04/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index 7316066da21..dc3080dcfbb 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -650,7 +650,7 @@ def _send_request(self, method, url, *args, **kwargs): if m is None: raise # pragma: no cover else: - host, path, err_no, err_msg = m.groups() + host, path, _err_no, err_msg = m.groups() raise ValueError("Requesting {0}{1}: {2}".format(host, path, err_msg)) # If content is DER, log the base64 of it instead of raw bytes, to keep From 880c35f3e3f8d1788024d40c6540d9d9ee1f7f01 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sat, 5 Aug 2017 10:39:04 -0400 Subject: [PATCH 05/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index dc3080dcfbb..ee4cf798536 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -643,7 +643,6 @@ def _send_request(self, method, url, *args, **kwargs): object at 0x108356c50>: Failed to establish a new connection: [Errno 65] No route to host',))""" - print e.message # pylint: disable=line-too-long err_regex = r".*host='(\S*)'.*Max retries exceeded with url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)" m = re.match(err_regex, str(e)) From 57e664077fdf006aede83c7934470787e2ee5d90 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sun, 6 Aug 2017 10:51:10 -0400 Subject: [PATCH 06/16] [#4535] - Unwrap max retries exceeded errors - fixing spacing --- acme/acme/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index ee4cf798536..2e07d34d70c 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -650,7 +650,7 @@ def _send_request(self, method, url, *args, **kwargs): raise # pragma: no cover else: host, path, _err_no, err_msg = m.groups() - raise ValueError("Requesting {0}{1}: {2}".format(host, path, err_msg)) + raise ValueError("Requesting {0}{1}:{2}".format(host, path, err_msg)) # If content is DER, log the base64 of it instead of raw bytes, to keep # binary data out of the logs. From 5fb1568b6e69866e4b0b7df0fd99a62bf0888b98 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sun, 6 Aug 2017 22:26:17 -0400 Subject: [PATCH 07/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 1c6b4a77ce1..172e94d74a2 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -628,7 +628,7 @@ def test_urllib_error(self): # pylint: disable=protected-access self.net._send_request('GET', "http://localhost:19123/nonexistent.txt") - # Python 2 + # Python Exceptions except ValueError as y: if "linux" in sys.platform: self.assertEqual("Requesting localhost/nonexistent: " @@ -637,11 +637,11 @@ def test_urllib_error(self): self.assertEqual("Requesting localhost/nonexistent: " "Connection refused", str(y)) - # Python 3 + # Requests Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover if "linux" in sys.platform: self.assertEqual("('Connection aborted.', " - "error('Connection refused'))", str(z)) + "error(111, 'Connection refused'))", str(z)) else: #pragma: no cover self.assertEqual("('Connection aborted.', " "error('Connection refused'))", str(z)) From 521f783020e3219bd698bbbe84397426c56e2dce Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sun, 6 Aug 2017 23:02:07 -0400 Subject: [PATCH 08/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client.py | 2 +- acme/acme/client_test.py | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index 2e07d34d70c..6fcee2fdc1b 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -647,7 +647,7 @@ def _send_request(self, method, url, *args, **kwargs): err_regex = r".*host='(\S*)'.*Max retries exceeded with url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)" m = re.match(err_regex, str(e)) if m is None: - raise # pragma: no cover + raise #pragma: no cover else: host, path, _err_no, err_msg = m.groups() raise ValueError("Requesting {0}{1}:{2}".format(host, path, err_msg)) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 172e94d74a2..ff0ac18ef06 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -7,7 +7,6 @@ import mock import requests -import sys from acme import challenges from acme import errors @@ -630,21 +629,8 @@ def test_urllib_error(self): # Python Exceptions except ValueError as y: - if "linux" in sys.platform: - self.assertEqual("Requesting localhost/nonexistent: " - "Connection refused", str(y)) - else: #pragma: no cover - self.assertEqual("Requesting localhost/nonexistent: " - "Connection refused", str(y)) - - # Requests Exceptions - except requests.exceptions.ConnectionError as z: #pragma: no cover - if "linux" in sys.platform: - self.assertEqual("('Connection aborted.', " - "error(111, 'Connection refused'))", str(z)) - else: #pragma: no cover - self.assertEqual("('Connection aborted.', " - "error('Connection refused'))", str(z)) + self.assertEqual("Requesting localhost/nonexistent: " + "Connection refused", str(y)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From 8555f4a0bdd83409cddebe831c706e12c056ecdd Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sun, 6 Aug 2017 23:30:11 -0400 Subject: [PATCH 09/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client.py | 2 +- acme/acme/client_test.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/acme/acme/client.py b/acme/acme/client.py index 6fcee2fdc1b..2e07d34d70c 100644 --- a/acme/acme/client.py +++ b/acme/acme/client.py @@ -647,7 +647,7 @@ def _send_request(self, method, url, *args, **kwargs): err_regex = r".*host='(\S*)'.*Max retries exceeded with url\: (\/\w*).*(\[Errno \d+\])([A-Za-z ]*)" m = re.match(err_regex, str(e)) if m is None: - raise #pragma: no cover + raise # pragma: no cover else: host, path, _err_no, err_msg = m.groups() raise ValueError("Requesting {0}{1}:{2}".format(host, path, err_msg)) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index ff0ac18ef06..6e6a0fecd51 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -627,11 +627,15 @@ def test_urllib_error(self): # pylint: disable=protected-access self.net._send_request('GET', "http://localhost:19123/nonexistent.txt") - # Python Exceptions + # Value Error Generated Exceptions except ValueError as y: self.assertEqual("Requesting localhost/nonexistent: " "Connection refused", str(y)) + # Requests Library Exceptions + except requests.exceptions.RequestException as z: + self.assertEqual("('Connection aborted.', error(111, 'Connection refused'))", str(z)) + class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" # pylint: disable=too-many-instance-attributes From 9b8c8f103eaeaa3f3060a253c62fddda90abbf88 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Sun, 6 Aug 2017 23:44:28 -0400 Subject: [PATCH 10/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 6e6a0fecd51..213706b71da 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -633,7 +633,7 @@ def test_urllib_error(self): "Connection refused", str(y)) # Requests Library Exceptions - except requests.exceptions.RequestException as z: + except requests.exceptions.RequestException as z: #pragma: no cover self.assertEqual("('Connection aborted.', error(111, 'Connection refused'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): From 9ae987d72bc3709081997b3c7ab383e693bceae0 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Mon, 7 Aug 2017 08:35:00 -0400 Subject: [PATCH 11/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 213706b71da..801e34bdf61 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -633,8 +633,8 @@ def test_urllib_error(self): "Connection refused", str(y)) # Requests Library Exceptions - except requests.exceptions.RequestException as z: #pragma: no cover - self.assertEqual("('Connection aborted.', error(111, 'Connection refused'))", str(z)) + except requests.exceptions.ConnectionError as z: #pragma: no cover + self.assertEqual("('Connection aborted.', error(99, 'Cannot assign requested address'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From f7dedae388ca338c3f218e680c4774109540f719 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Mon, 7 Aug 2017 08:39:39 -0400 Subject: [PATCH 12/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 801e34bdf61..813898d2094 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -634,7 +634,7 @@ def test_urllib_error(self): # Requests Library Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover - self.assertEqual("('Connection aborted.', error(99, 'Cannot assign requested address'))", str(z)) + self.assertEqual("('Connection aborted.', error(111, 'Connection Refused'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From 2e7ec00e8c5a605c272a72a702f34803463bc5df Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Mon, 7 Aug 2017 08:55:43 -0400 Subject: [PATCH 13/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 813898d2094..6509f951b7b 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -634,7 +634,7 @@ def test_urllib_error(self): # Requests Library Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover - self.assertEqual("('Connection aborted.', error(111, 'Connection Refused'))", str(z)) + self.assertEqual("('Connection aborted.', error(111, 'Connection refused'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From 8a78ef9675e1fbed7e5734a5e95c5d121dde0553 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Mon, 7 Aug 2017 15:33:01 -0400 Subject: [PATCH 14/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 6509f951b7b..801e34bdf61 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -634,7 +634,7 @@ def test_urllib_error(self): # Requests Library Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover - self.assertEqual("('Connection aborted.', error(111, 'Connection refused'))", str(z)) + self.assertEqual("('Connection aborted.', error(99, 'Cannot assign requested address'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From b3216727daffa93391e939cadc1a266978240f22 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Mon, 7 Aug 2017 19:34:20 -0400 Subject: [PATCH 15/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index 801e34bdf61..d97b4920c9b 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -634,7 +634,8 @@ def test_urllib_error(self): # Requests Library Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover - self.assertEqual("('Connection aborted.', error(99, 'Cannot assign requested address'))", str(z)) + self.assertEqual("('Connection aborted.'," + "error(111, 'Connection refused'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase): """Tests for acme.client.ClientNetwork which mock out response.""" From a8e1df6e551e1322fc098d2bcccf5e90bb9d0dd0 Mon Sep 17 00:00:00 2001 From: Bob Strecansky Date: Mon, 7 Aug 2017 20:15:05 -0400 Subject: [PATCH 16/16] [#4535] - Unwrap max retries exceeded errors --- acme/acme/client_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/client_test.py b/acme/acme/client_test.py index d97b4920c9b..4bd762865e3 100644 --- a/acme/acme/client_test.py +++ b/acme/acme/client_test.py @@ -634,7 +634,7 @@ def test_urllib_error(self): # Requests Library Exceptions except requests.exceptions.ConnectionError as z: #pragma: no cover - self.assertEqual("('Connection aborted.'," + self.assertEqual("('Connection aborted.', " "error(111, 'Connection refused'))", str(z)) class ClientNetworkWithMockedResponseTest(unittest.TestCase):