summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2014-12-11 21:18:12 -0500
committerBarry Warsaw2014-12-11 21:18:12 -0500
commitfe7d286db796630b3bef326bd5106591940c0b5f (patch)
tree4a732db60a62d222a8dd998f596789022bbc64bf
parent930a1c05b441000fbe5c3c4d8ae36d08bfe3dcdd (diff)
downloadmailman-fe7d286db796630b3bef326bd5106591940c0b5f.tar.gz
mailman-fe7d286db796630b3bef326bd5106591940c0b5f.tar.zst
mailman-fe7d286db796630b3bef326bd5106591940c0b5f.zip
-rw-r--r--src/mailman/rest/helpers.py8
-rw-r--r--src/mailman/rest/root.py3
-rw-r--r--src/mailman/rest/wsgiapp.py2
-rw-r--r--src/mailman/testing/helpers.py5
4 files changed, 12 insertions, 6 deletions
diff --git a/src/mailman/rest/helpers.py b/src/mailman/rest/helpers.py
index 0bc312b1f..2b79a0e8a 100644
--- a/src/mailman/rest/helpers.py
+++ b/src/mailman/rest/helpers.py
@@ -59,7 +59,7 @@ def path_to(resource):
:return: The full path to the resource.
:rtype: bytes
"""
- return b'{0}://{1}:{2}/{3}/{4}'.format(
+ return '{0}://{1}:{2}/{3}/{4}'.format(
('https' if as_boolean(config.webservice.use_https) else 'http'),
config.webservice.hostname,
config.webservice.port,
@@ -107,8 +107,10 @@ def etag(resource):
assert 'http_etag' not in resource, 'Resource already etagged'
# Calculate the tag from a predictable (i.e. sorted) representation of the
# dictionary. The actual details aren't so important. pformat() is
- # guaranteed to sort the keys.
- etag = hashlib.sha1(pformat(resource)).hexdigest()
+ # guaranteed to sort the keys, however it returns a str and the hash
+ # library requires a bytes. Use the safest possible encoding.
+ hashfood = pformat(resource).encode('raw-unicode-escape')
+ etag = hashlib.sha1(hashfood).hexdigest()
resource['http_etag'] = '"{0}"'.format(etag)
return json.dumps(resource, cls=ExtendedEncoder)
diff --git a/src/mailman/rest/root.py b/src/mailman/rest/root.py
index 93a8f0086..a8e975fed 100644
--- a/src/mailman/rest/root.py
+++ b/src/mailman/rest/root.py
@@ -69,7 +69,8 @@ class Root:
b'401 Unauthorized',
b'The REST API requires authentication')
if request.auth.startswith('Basic '):
- credentials = b64decode(request.auth[6:])
+ # b64decode() returns bytes, but we require a str.
+ credentials = b64decode(request.auth[6:]).decode('utf-8')
username, password = credentials.split(':', 1)
if (username != config.webservice.admin_user or
password != config.webservice.admin_pass):
diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py
index 698c4269d..445adf278 100644
--- a/src/mailman/rest/wsgiapp.py
+++ b/src/mailman/rest/wsgiapp.py
@@ -85,7 +85,7 @@ class RootedAPI(API):
if matcher is _missing:
continue
result = None
- if isinstance(matcher, basestring):
+ if isinstance(matcher, str):
# Is the matcher string a regular expression or plain
# string? If it starts with a caret, it's a regexp.
if matcher.startswith('^'):
diff --git a/src/mailman/testing/helpers.py b/src/mailman/testing/helpers.py
index 1de0e98cf..882e69cd9 100644
--- a/src/mailman/testing/helpers.py
+++ b/src/mailman/testing/helpers.py
@@ -333,7 +333,10 @@ def call_api(url, data=None, method=None, username=None, password=None):
basic_auth = '{0}:{1}'.format(
(config.webservice.admin_user if username is None else username),
(config.webservice.admin_pass if password is None else password))
- headers['Authorization'] = 'Basic ' + b64encode(basic_auth)
+ # b64encode() requires a bytes, but the header value must be str. Do the
+ # necessary conversion dances.
+ token = b64encode(basic_auth.encode('utf-8')).decode('ascii')
+ headers['Authorization'] = 'Basic ' + token
response, content = Http().request(url, method, data, headers)
# If we did not get a 2xx status code, make this look like a urllib2
# exception, for backward compatibility with existing doctests.