diff --git a/django/utils/http.py b/django/utils/http.py index 2375f95b5b..aa6d56d34a 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -10,7 +10,7 @@ from binascii import Error as BinasciiError from email.utils import formatdate from django.utils.datastructures import MultiValueDict -from django.utils.encoding import force_str, force_text +from django.utils.encoding import force_bytes, force_str, force_text from django.utils.functional import allow_lazy from django.utils import six from django.utils.six.moves.urllib.parse import ( @@ -227,7 +227,7 @@ def urlsafe_base64_decode(s): Decodes a base64 encoded string, adding back any trailing equal signs that might have been stripped. """ - s = s.encode('utf-8') # base64encode should only return ASCII. + s = force_bytes(s) try: return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b'=')) except (LookupError, BinasciiError) as e: diff --git a/tests/utils_tests/test_http.py b/tests/utils_tests/test_http.py index 3f512ad80b..db24d1c9f2 100644 --- a/tests/utils_tests/test_http.py +++ b/tests/utils_tests/test_http.py @@ -119,6 +119,12 @@ class TestUtilsHttp(unittest.TestCase): '/url%20with%20spaces/'): self.assertTrue(http.is_safe_url(good_url, host='testserver'), "%s should be allowed" % good_url) + def test_urlsafe_base64_roundtrip(self): + bytestring = b'foo' + encoded = http.urlsafe_base64_encode(bytestring) + decoded = http.urlsafe_base64_decode(encoded) + self.assertEqual(bytestring, decoded) + class ETagProcessingTests(unittest.TestCase): def test_parsing(self):