From df1f4f3e3932a9653b7b1731e121c51c7fdf31e1 Mon Sep 17 00:00:00 2001 From: "Lisak, Peter" <peter.lisak@firma.seznam.cz> Date: Tue, 6 Oct 2015 10:08:02 +0200 Subject: [PATCH] swiftclient content-type header According to help `swift upload -h` you can add a customized request header 'Content-Type'. But actually it is ignored (cleared and default is used) if subcommand is upload. Subcommand post works as expected in help. Bug fix: Use 'Content-Type' from the customized request headers also if uploading. Change-Id: If0d1354b6214b909527341078fe1769aa6587457 --- swiftclient/client.py | 10 +++++--- tests/functional/test_swiftclient.py | 34 ++++++++++++++++++++++++++++ tests/unit/test_swiftclient.py | 18 +++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/swiftclient/client.py b/swiftclient/client.py index f2d3098c..cad115f6 100644 --- a/swiftclient/client.py +++ b/swiftclient/client.py @@ -1028,8 +1028,11 @@ 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, an - empty string value will be sent + + :param content_type: value to send as content-type header, overriding any + value included in the headers param; if None and no + value is found in the headers param, 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) @@ -1071,7 +1074,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 + elif 'Content-Type' not in headers: + # python-requests sets application/x-www-form-urlencoded otherwise headers['Content-Type'] = '' if not contents: headers['Content-Length'] = '0' diff --git a/tests/functional/test_swiftclient.py b/tests/functional/test_swiftclient.py index 2be280da..35a5ea7e 100644 --- a/tests/functional/test_swiftclient.py +++ b/tests/functional/test_swiftclient.py @@ -217,6 +217,40 @@ class TestFunctional(testtools.TestCase): self.assertEqual('application/octet-stream', hdrs.get('content-type')) + # Same but with content_type + self.conn.put_object( + self.containername, self.objectname, + content_type='text/plain', contents=self.test_data) + hdrs = self.conn.head_object(self.containername, self.objectname) + self.assertEqual(str(len(self.test_data)), + hdrs.get('content-length')) + self.assertEqual(self.etag, hdrs.get('etag')) + self.assertEqual('text/plain', + hdrs.get('content-type')) + + # Same but with content-type in headers + self.conn.put_object( + self.containername, self.objectname, + headers={'Content-Type': 'text/plain'}, contents=self.test_data) + hdrs = self.conn.head_object(self.containername, self.objectname) + self.assertEqual(str(len(self.test_data)), + hdrs.get('content-length')) + self.assertEqual(self.etag, hdrs.get('etag')) + self.assertEqual('text/plain', + hdrs.get('content-type')) + + # content_type rewrites content-type in headers + self.conn.put_object( + self.containername, self.objectname, + content_type='image/jpeg', + headers={'Content-Type': 'text/plain'}, contents=self.test_data) + hdrs = self.conn.head_object(self.containername, self.objectname) + self.assertEqual(str(len(self.test_data)), + hdrs.get('content-length')) + self.assertEqual(self.etag, hdrs.get('etag')) + self.assertEqual('image/jpeg', + hdrs.get('content-type')) + # Same but with content-length self.conn.put_object( self.containername, self.objectname, diff --git a/tests/unit/test_swiftclient.py b/tests/unit/test_swiftclient.py index 53fcccb7..68af46ab 100644 --- a/tests/unit/test_swiftclient.py +++ b/tests/unit/test_swiftclient.py @@ -1013,6 +1013,24 @@ class TestPutObject(MockHttpTest): request_header = resp.requests_params['headers'] self.assertEqual(request_header['content-type'], b'') + def test_content_type_in_headers(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 + + # title-case header + hdrs = {'Content-Type': 'text/Plain'} + c.put_object(url='http://www.test.com', http_conn=conn, headers=hdrs) + request_header = resp.requests_params['headers'] + self.assertEqual(request_header['content-type'], b'text/Plain') + + # method param overrides headers + c.put_object(url='http://www.test.com', http_conn=conn, headers=hdrs, + content_type='image/jpeg') + request_header = resp.requests_params['headers'] + self.assertEqual(request_header['content-type'], b'image/jpeg') + class TestPostObject(MockHttpTest):