From 11a2289d381fa98bc28973ead1511c8b2bd6c656 Mon Sep 17 00:00:00 2001 From: Yossi Gottlieb Date: Fri, 29 Dec 2017 21:00:43 +0200 Subject: [PATCH 1/3] Handle URL-encoded passwords and service names. This is required to support non URL safe passwords or service names, which should be url encoded in this case. --- redis_sentinel_url.py | 5 +++-- test_redis_sentinel_url.py | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/redis_sentinel_url.py b/redis_sentinel_url.py index 8ecbdf0..bbff392 100644 --- a/redis_sentinel_url.py +++ b/redis_sentinel_url.py @@ -13,6 +13,7 @@ # limitations under the License. from collections import namedtuple +import urllib try: import urllib.parse as urlparse except ImportError: # pragma: no cover @@ -74,7 +75,7 @@ def parse_host(s): hostspec = url.netloc if auth and ':' in auth: - _, password = auth.split(':', 1) + password = urllib.unquote(auth.split(':', 1)[1]) else: password = None @@ -136,7 +137,7 @@ def parse_host(s): if 'service' in url_options: service_name = url_options.pop('service') elif len(path_parts) >= 1: - service_name = path_parts[0] + service_name = urllib.unquote(path_parts[0]) else: service_name = None diff --git a/test_redis_sentinel_url.py b/test_redis_sentinel_url.py index 96dcd3b..ce1fead 100644 --- a/test_redis_sentinel_url.py +++ b/test_redis_sentinel_url.py @@ -106,6 +106,10 @@ def test_with_password(self): self.assertEquals(parsed.sentinel_options, {}) self.assertEquals(parsed.client_options['password'], 'thesecret') + def test_with_url_encoding(self): + parsed = parse_sentinel_url('redis+sentinel://:%20%20@hostname:7000/%2F%2Fmydb%2F%2F/0') + self.assertEquals(parsed.client_options['password'], ' ') + self.assertEqual(parsed.default_client, DefaultClient('master', '//mydb//')) class FakeRedis(MagicMock): def __init__(self, host='localhost', port=6379, From e67ae05ee67549d75353f44bbcfa3cbd664628a4 Mon Sep 17 00:00:00 2001 From: Yossi Gottlieb Date: Fri, 29 Dec 2017 21:13:11 +0200 Subject: [PATCH 2/3] flake8 spacing fix. --- test_redis_sentinel_url.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test_redis_sentinel_url.py b/test_redis_sentinel_url.py index ce1fead..1ce8ebd 100644 --- a/test_redis_sentinel_url.py +++ b/test_redis_sentinel_url.py @@ -111,6 +111,7 @@ def test_with_url_encoding(self): self.assertEquals(parsed.client_options['password'], ' ') self.assertEqual(parsed.default_client, DefaultClient('master', '//mydb//')) + class FakeRedis(MagicMock): def __init__(self, host='localhost', port=6379, db=0, password=None, socket_timeout=None, From 11a39b8577c9af1418be00f89292cf991181f590 Mon Sep 17 00:00:00 2001 From: Yossi Gottlieb Date: Fri, 29 Dec 2017 21:24:31 +0200 Subject: [PATCH 3/3] Fix Python 3.x issue. --- redis_sentinel_url.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/redis_sentinel_url.py b/redis_sentinel_url.py index bbff392..81045ed 100644 --- a/redis_sentinel_url.py +++ b/redis_sentinel_url.py @@ -13,11 +13,16 @@ # limitations under the License. from collections import namedtuple -import urllib try: import urllib.parse as urlparse except ImportError: # pragma: no cover import urlparse + +try: + from urllib.parse import unquote +except ImportError: # pragma: no cover + from urllib import unquote + import redis import redis.sentinel # requires redis-py 2.9.0+ import sys @@ -75,7 +80,7 @@ def parse_host(s): hostspec = url.netloc if auth and ':' in auth: - password = urllib.unquote(auth.split(':', 1)[1]) + password = unquote(auth.split(':', 1)[1]) else: password = None @@ -137,7 +142,7 @@ def parse_host(s): if 'service' in url_options: service_name = url_options.pop('service') elif len(path_parts) >= 1: - service_name = urllib.unquote(path_parts[0]) + service_name = unquote(path_parts[0]) else: service_name = None