diff --git a/swiftclient/client.py b/swiftclient/client.py index 5494f34d..a7d0dafb 100644 --- a/swiftclient/client.py +++ b/swiftclient/client.py @@ -186,10 +186,12 @@ class HTTPConnection: for header, value in items: value = encode_utf8(value) header = header.lower() - for target_type in 'container', 'account', 'object': - prefix = 'x-%s-meta-' % target_type - if header.startswith(prefix): - header = encode_utf8(header) + if isinstance(header, six.string_types): + for target_type in 'container', 'account', 'object': + prefix = 'x-%s-meta-' % target_type + if header.startswith(prefix): + header = encode_utf8(header) + break ret[header] = value return ret @@ -899,9 +901,8 @@ def put_object(url, token=None, container=None, name=None, contents=None, :param chunk_size: chunk size of data to write; it defaults to 65536; used only if the contents object has a 'read' method, e.g. file-like objects, ignored otherwise - :param content_type: value to send as content-type header; if None, no - content-type will be set (remote end will likely try - to auto-detect it) + :param content_type: value to send as content-type header; if None, an + empty string value will be sent :param headers: additional headers to include in the request, if any :param http_conn: HTTP connection object (If None, it will create the conn object) @@ -940,6 +941,8 @@ def put_object(url, token=None, container=None, name=None, contents=None, content_length = int(v) if content_type is not None: headers['Content-Type'] = content_type + else: # python-requests sets application/x-www-form-urlencoded otherwise + headers['Content-Type'] = '' if not contents: headers['Content-Length'] = '0' if hasattr(contents, 'read'): diff --git a/tests/functional/test_swiftclient.py b/tests/functional/test_swiftclient.py index 6631d369..3721e518 100644 --- a/tests/functional/test_swiftclient.py +++ b/tests/functional/test_swiftclient.py @@ -259,7 +259,7 @@ class TestFunctional(testtools.TestCase): self.containername, self.objectname, resp_chunk_size=10) self.assertTrue(isinstance(body, types.GeneratorType)) - self.assertEqual(self.test_data, ''.join(body)) + self.assertEqual(self.test_data, b''.join(body)) def test_post_account(self): self.conn.post_account({'x-account-meta-data': 'Something'}) diff --git a/tests/unit/test_swiftclient.py b/tests/unit/test_swiftclient.py index 0819475b..2e7a8073 100644 --- a/tests/unit/test_swiftclient.py +++ b/tests/unit/test_swiftclient.py @@ -730,6 +730,16 @@ class TestPutObject(MockHttpTest): self.assertTrue(request_header['etag'], '1234-5678') self.assertTrue(request_header['content-type'], 'text/plain') + def test_no_content_type(self): + conn = c.http_connection(u'http://www.test.com/') + resp = MockHttpResponse(status=200) + conn[1].getresponse = resp.fake_response + conn[1]._request = resp._fake_request + + c.put_object(url='http://www.test.com', http_conn=conn) + request_header = resp.requests_params['headers'] + self.assertEqual(request_header['content-type'], b'') + class TestPostObject(MockHttpTest): @@ -746,7 +756,10 @@ class TestPostObject(MockHttpTest): u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91') text = u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91' headers = {'X-Header1': text, - 'X-2': '1', 'X-3': {'a': 'b'}, 'a-b': '.x:yz mn:kl:qr'} + b'X-Header2': 'value', + 'X-2': '1', 'X-3': {'a': 'b'}, 'a-b': '.x:yz mn:kl:qr', + 'X-Object-Meta-Header-not-encoded': text, + b'X-Object-Meta-Header-encoded': 'value'} resp = MockHttpResponse() conn[1].getresponse = resp.fake_response @@ -757,6 +770,11 @@ class TestPostObject(MockHttpTest): # Test unicode header self.assertIn(('x-header1', text.encode('utf8')), resp.buffer) + self.assertIn((b'x-object-meta-header-not-encoded', + text.encode('utf8')), resp.buffer) + self.assertIn((b'x-object-meta-header-encoded', b'value'), + resp.buffer) + self.assertIn((b'x-header2', b'value'), resp.buffer) def test_server_error(self): body = 'c' * 60