summaryrefslogtreecommitdiff
path: root/glanceclient
diff options
context:
space:
mode:
authorwangxiyuan <wangxiyuan1007@gmail.com>2018-07-18 11:30:10 +0800
committerwangxiyuan <wangxiyuan@huawei.com>2018-07-25 16:22:43 +0800
commit818362147d0622752d051bd78ae839497a602e44 (patch)
tree1aa3c3032abfc31bd29534c407f35f87300f256e /glanceclient
parentccbd86ba131d319e512bf4855e9b3152cc073fee (diff)
downloadpython-glanceclient-818362147d0622752d051bd78ae839497a602e44.tar.gz
Do not quote '+' for token header
The token in request header may contain url char, such as '+', if quote it, '+' will change to '%2B' which will lead to 401 error. Our CI doesn't notice this bug because Keystone use fernet token which doesn't contain url char by default. But token format in keystone is plugable, some out-tree token formats may contain url char (for example, PKI/PKIZ token). So we should skip quote token to avoiding information changing. Closes-bug: #1783290 Change-Id: I5aa71b3e2b9b19581e46ccf8a80eda5d637f17d1
Diffstat (limited to 'glanceclient')
-rw-r--r--glanceclient/common/http.py25
-rw-r--r--glanceclient/tests/unit/test_http.py6
2 files changed, 18 insertions, 13 deletions
diff --git a/glanceclient/common/http.py b/glanceclient/common/http.py
index 84cdc69..b5bea8a 100644
--- a/glanceclient/common/http.py
+++ b/glanceclient/common/http.py
@@ -42,6 +42,7 @@ LOG = logging.getLogger(__name__)
USER_AGENT = 'python-glanceclient'
CHUNKSIZE = 1024 * 64 # 64kB
REQ_ID_HEADER = 'X-OpenStack-Request-ID'
+TOKEN_HEADERS = ['X-Auth-Token', 'X-Service-Token']
def encode_headers(headers):
@@ -61,16 +62,20 @@ def encode_headers(headers):
# Bug #1766235: According to RFC 8187, headers must be encoded as ASCII.
# So we first %-encode them to get them into range < 128 and then turn
# them into ASCII.
- if six.PY2:
- # incoming items may be unicode, so get them into something
- # the py2 version of urllib can handle before percent encoding
- encoded_dict = dict((urlparse.quote(encodeutils.safe_encode(h)),
- urlparse.quote(encodeutils.safe_encode(v)))
- for h, v in headers.items() if v is not None)
- else:
- encoded_dict = dict((urlparse.quote(h), urlparse.quote(v))
- for h, v in headers.items() if v is not None)
-
+ encoded_dict = {}
+ for h, v in headers.items():
+ if v is not None:
+ # if the item is token, do not quote '+' as well.
+ safe = '+/' if h in TOKEN_HEADERS else '/'
+ if six.PY2:
+ # incoming items may be unicode, so get them into something
+ # the py2 version of urllib can handle before percent encoding
+ key = urlparse.quote(encodeutils.safe_encode(h), safe)
+ value = urlparse.quote(encodeutils.safe_encode(v), safe)
+ else:
+ key = urlparse.quote(h, safe)
+ value = urlparse.quote(v, safe)
+ encoded_dict[key] = value
return dict((encodeutils.safe_encode(h, encoding='ascii'),
encodeutils.safe_encode(v, encoding='ascii'))
for h, v in encoded_dict.items())
diff --git a/glanceclient/tests/unit/test_http.py b/glanceclient/tests/unit/test_http.py
index efd15bf..cdc1895 100644
--- a/glanceclient/tests/unit/test_http.py
+++ b/glanceclient/tests/unit/test_http.py
@@ -467,11 +467,11 @@ class TestClient(testtools.TestCase):
headers = self.mock.last_request.headers
self.assertEqual(refreshed_token, headers['X-Auth-Token'])
# regression check for bug 1448080
- unicode_token = u'ni\xf1o'
+ unicode_token = u'ni\xf1o+'
http_client.auth_token = unicode_token
http_client.get(path)
headers = self.mock.last_request.headers
# Bug #1766235: According to RFC 8187, headers must be
# encoded as 7-bit ASCII, so expect to see only displayable
- # chars in percent-encoding
- self.assertEqual(b'ni%C3%B1o', headers['X-Auth-Token'])
+ # chars in percent-encoding. The '+' char will be not be changed.
+ self.assertEqual(b'ni%C3%B1o+', headers['X-Auth-Token'])