Browse Source

Fix logging of encoded headers

A change introduced in 3.5.0 sorts headers, but runs into a problem
when the headers are bytes, such as the headers provided by the
python-glanceclient.

requests expects headers to be str type in both python2 and python3.
This means in python2 we need to encode unicode objects as ASCII (the
encoding that should be used for HTTP headers) and in python3 we need to
decode bytes as ASCII into str.

Change-Id: Ib81497c3a873616c22ba68256c596a6fb113e11e
Closes-bug: #1766235
Brian Rosmaita 1 year ago
parent
commit
35de6ebe93
No account linked to committer's email address

+ 24
- 0
keystoneauth1/session.py View File

@@ -79,6 +79,26 @@ def _mv_legacy_headers_for_service(mv_service_type):
79 79
     return headers
80 80
 
81 81
 
82
+def _sanitize_headers(headers):
83
+    """Ensure headers are strings and not bytes."""
84
+    str_dict = {}
85
+    for k, v in headers.items():
86
+        if six.PY3:
87
+            # requests expects headers to be str type in python3, which means
88
+            # if we get a bytes we need to decode it into a str
89
+            k = k.decode('ASCII') if isinstance(k, six.binary_type) else k
90
+            if v is not None:
91
+                v = v.decode('ASCII') if isinstance(v, six.binary_type) else v
92
+        else:
93
+            # requests expects headers to be str type in python2, which means
94
+            # if we get a unicode we need to encode it to ASCII into a str
95
+            k = k.encode('ASCII') if isinstance(k, six.text_type) else k
96
+            if v is not None:
97
+                v = v.encode('ASCII') if isinstance(v, six.text_type) else v
98
+        str_dict[k] = v
99
+    return str_dict
100
+
101
+
82 102
 class _JSONEncoder(json.JSONEncoder):
83 103
 
84 104
     def default(self, o):
@@ -711,6 +731,10 @@ class Session(object):
711 731
         for k, v in self.additional_headers.items():
712 732
             headers.setdefault(k, v)
713 733
 
734
+        # Bug #1766235: some headers may be bytes
735
+        headers = _sanitize_headers(headers)
736
+        kwargs['headers'] = headers
737
+
714 738
         kwargs.setdefault('verify', self.verify)
715 739
 
716 740
         if requests_auth:

+ 8
- 1
keystoneauth1/tests/unit/test_session.py View File

@@ -17,6 +17,7 @@ import sys
17 17
 import uuid
18 18
 
19 19
 import mock
20
+from oslo_utils import encodeutils
20 21
 import requests
21 22
 import requests.auth
22 23
 import six
@@ -987,7 +988,12 @@ class SessionAuthTests(utils.TestCase):
987 988
                 'X-OpenStack-Request-ID': request_id,
988 989
             })
989 990
 
990
-        resp = sess.get(self.TEST_URL)
991
+        resp = sess.get(
992
+            self.TEST_URL,
993
+            headers={
994
+                encodeutils.safe_encode('x-bytes-header'):
995
+                encodeutils.safe_encode('bytes-value')
996
+            })
991 997
 
992 998
         self.assertEqual(response, resp.json())
993 999
 
@@ -998,6 +1004,7 @@ class SessionAuthTests(utils.TestCase):
998 1004
 
999 1005
         self.assertIn('curl -g -i -X GET {url}'.format(url=self.TEST_URL),
1000 1006
                       request_output)
1007
+        self.assertIn('-H "x-bytes-header: bytes-value"', request_output)
1001 1008
         self.assertEqual('[200] Content-Type: application/json '
1002 1009
                          'X-OpenStack-Request-ID: '
1003 1010
                          '{id}'.format(id=request_id), response_output)

+ 6
- 0
releasenotes/notes/bug-1766235wq-0de60d0f996c6bfb.yaml View File

@@ -0,0 +1,6 @@
1
+---
2
+fixes:
3
+  - |
4
+    [`bug 1766235 <https://bugs.launchpad.net/keystoneauth/+bug/1766235>`_]
5
+    Fixed an issue where passing headers in as bytes rather than strings
6
+    would cause a sorting issue.

Loading…
Cancel
Save