From ab60e08e2e34ac4a87bc6c1701c6ace69bb392cf Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Thu, 25 Aug 2016 10:51:29 -0700 Subject: Convert numeric and boolean header values to strings Recently, requests got a bit more picky about what types of data it will accept as header values [1]. The reasons for this are generally sound; str()ing arbitrary objects just before pushing them out a socket may not do what the developer wanted/expected. However, there are a few standard types that developers may be sending that we should convert for them as a convenience. Now, we'll convert all int, float, and bool values to strings before sending them on to requests. Change-Id: I6c2f451009cb03cb78812f54e4ed8566076de821 Closes-Bug: 1614932 --- swiftclient/client.py | 7 +++++++ tests/functional/test_swiftclient.py | 11 ++++++++++- tests/unit/test_swiftclient.py | 7 ++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/swiftclient/client.py b/swiftclient/client.py index 602489d..7515f7c 100644 --- a/swiftclient/client.py +++ b/swiftclient/client.py @@ -211,6 +211,13 @@ def quote(value, safe='/'): def encode_utf8(value): + if type(value) in six.integer_types + (float, bool): + # As of requests 2.11.0, headers must be byte- or unicode-strings. + # Convert some known-good types as a convenience for developers. + # Note that we *don't* convert subclasses, as they may have overriddden + # __str__ or __repr__. + # See https://github.com/kennethreitz/requests/pull/3366 for more info + value = str(value) if isinstance(value, six.text_type): value = value.encode('utf8') return value diff --git a/tests/functional/test_swiftclient.py b/tests/functional/test_swiftclient.py index 6e19abd..0e6a346 100644 --- a/tests/functional/test_swiftclient.py +++ b/tests/functional/test_swiftclient.py @@ -400,10 +400,19 @@ class TestFunctional(unittest.TestCase): def test_post_object(self): self.conn.post_object(self.containername, self.objectname, - {'x-object-meta-color': 'Something'}) + {'x-object-meta-color': 'Something', + 'x-object-meta-uni': b'\xd8\xaa'.decode('utf8'), + 'x-object-meta-int': 123, + 'x-object-meta-float': 45.67, + 'x-object-meta-bool': False}) headers = self.conn.head_object(self.containername, self.objectname) self.assertEqual('Something', headers.get('x-object-meta-color')) + self.assertEqual(b'\xd8\xaa'.decode('utf-8'), + headers.get('x-object-meta-uni')) + self.assertEqual('123', headers.get('x-object-meta-int')) + self.assertEqual('45.67', headers.get('x-object-meta-float')) + self.assertEqual('False', headers.get('x-object-meta-bool')) def test_copy_object(self): self.conn.put_object( diff --git a/tests/unit/test_swiftclient.py b/tests/unit/test_swiftclient.py index 4e4c9f4..09d8e76 100644 --- a/tests/unit/test_swiftclient.py +++ b/tests/unit/test_swiftclient.py @@ -185,9 +185,9 @@ class TestHttpHelpers(MockHttpTest): def test_encode_meta_headers(self): headers = {'abc': '123', - u'x-container-meta-\u0394': '123', - u'x-account-meta-\u0394': '123', - u'x-object-meta-\u0394': '123'} + u'x-container-meta-\u0394': 123, + u'x-account-meta-\u0394': 12.3, + u'x-object-meta-\u0394': True} r = swiftclient.encode_meta_headers(headers) @@ -199,6 +199,7 @@ class TestHttpHelpers(MockHttpTest): for k, v in r.items(): self.assertIs(type(k), binary_type) self.assertIs(type(v), binary_type) + self.assertIn(v, (b'123', b'12.3', b'True')) def test_set_user_agent_default(self): _junk, conn = c.http_connection('http://www.example.com') -- cgit v1.2.1