From: Ian Cordasco Date: Sat, 27 Dec 2014 02:02:16 +0000 (-0600) Subject: Attempt to quote anyway if unquoting fails X-Git-Tag: v2.5.2~10^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=751b35c346e1cf373fcf4b2f19683ebfbd9dae3d;p=services%2Fpython-requests.git Attempt to quote anyway if unquoting fails Fixes #2356 --- diff --git a/requests/utils.py b/requests/utils.py index 7467941..2941396 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -418,10 +418,18 @@ def requote_uri(uri): This function passes the given URI through an unquote/quote cycle to ensure that it is fully and consistently quoted. """ - # Unquote only the unreserved characters - # Then quote only illegal characters (do not quote reserved, unreserved, - # or '%') - return quote(unquote_unreserved(uri), safe="!#$%&'()*+,/:;=?@[]~") + safe_with_percent = "!#$%&'()*+,/:;=?@[]~" + safe_without_percent = "!#$&'()*+,/:;=?@[]~" + try: + # Unquote only the unreserved characters + # Then quote only illegal characters (do not quote reserved, + # unreserved, or '%') + return quote(unquote_unreserved(uri), safe=safe_with_percent) + except InvalidURL: + # We couldn't unquote the given URI, so let's try quoting it, but + # there may be unquoted '%'s in the URI. We need to make sure they're + # properly quoted so they do not cause issues elsewhere. + return quote(uri, safe=safe_without_percent) def address_in_network(ip, net): diff --git a/test_requests.py b/test_requests.py index 34348d3..9337b0e 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1301,6 +1301,22 @@ class UtilsTestCase(unittest.TestCase): assert username == percent_encoding_test_chars assert password == percent_encoding_test_chars + def test_requote_uri_with_unquoted_percents(self): + """Ensure we handle unquoted percent signs in redirects. + + See: https://github.com/kennethreitz/requests/issues/2356 + """ + from requests.utils import requote_uri + bad_uri = 'http://example.com/fiz?buz=%ppicture' + quoted = 'http://example.com/fiz?buz=%25ppicture' + assert quoted == requote_uri(bad_uri) + + def test_requote_uri_properly_requotes(self): + """Ensure requoting doesn't break expectations.""" + from requests.utils import requote_uri + quoted = 'http://example.com/fiz?buz=%25ppicture' + assert quoted == requote_uri(quoted) + class TestMorselToCookieExpires(unittest.TestCase):