diff --git a/keystoneclient/middleware/auth_token.py b/keystoneclient/middleware/auth_token.py index 0267812b..b96ea006 100644 --- a/keystoneclient/middleware/auth_token.py +++ b/keystoneclient/middleware/auth_token.py @@ -109,6 +109,7 @@ import logging import os import stat import time +import urllib import webob import webob.exc @@ -177,6 +178,11 @@ def will_expire_soon(expiry): return expiry < soon +def safe_quote(s): + """URL-encode strings that are not already URL-encoded.""" + return urllib.quote(s) if s == urllib.unquote(s) else s + + class InvalidUserToken(Exception): pass @@ -692,9 +698,10 @@ class AuthProtocol(object): """ headers = {'X-Auth-Token': self.get_admin_token()} - response, data = self._json_request('GET', - '/v2.0/tokens/%s' % user_token, - additional_headers=headers) + response, data = self._json_request( + 'GET', + '/v2.0/tokens/%s' % safe_quote(user_token), + additional_headers=headers) if response.status == 200: self._cache_put(user_token, data) diff --git a/tests/test_auth_token_middleware.py b/tests/test_auth_token_middleware.py index 79cbc910..e94cfcf6 100644 --- a/tests/test_auth_token_middleware.py +++ b/tests/test_auth_token_middleware.py @@ -668,3 +668,11 @@ class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest): fortyseconds = datetime.datetime.utcnow() + datetime.timedelta( seconds=40) self.assertFalse(auth_token.will_expire_soon(fortyseconds)) + + +class TokenEncodingTest(unittest.TestCase): + def test_unquoted_token(self): + self.assertEqual('foo%20bar', auth_token.safe_quote('foo bar')) + + def test_quoted_token(self): + self.assertEqual('foo%20bar', auth_token.safe_quote('foo%20bar'))