From 7cb99d3157f24e81737463302c937f1c251b7084 Mon Sep 17 00:00:00 2001
From: Mahati <mahati.chamarthy@gmail.com>
Date: Tue, 15 Sep 2015 14:34:53 +0530
Subject: [PATCH] Add headers parameter

Headers parameter is required when passing client key for encryption.
It is missing for get_container and head_object.

Change-Id: I35c3b266b3c733f6b1629de4c683ea7d40128032
---
 swiftclient/client.py          | 25 +++++++++++++++++--------
 tests/unit/test_swiftclient.py | 27 +++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/swiftclient/client.py b/swiftclient/client.py
index e0d35a8e..1913ea36 100644
--- a/swiftclient/client.py
+++ b/swiftclient/client.py
@@ -638,7 +638,7 @@ def post_account(url, token, headers, http_conn=None, response_dict=None,
 def get_container(url, token, container, marker=None, limit=None,
                   prefix=None, delimiter=None, end_marker=None,
                   path=None, http_conn=None,
-                  full_listing=False, service_token=None):
+                  full_listing=False, service_token=None, headers=None):
     """
     Get a listing of objects for the container.
 
@@ -662,10 +662,15 @@ def get_container(url, token, container, marker=None, limit=None,
     """
     if not http_conn:
         http_conn = http_connection(url)
+    if headers:
+        headers = dict(headers)
+    else:
+        headers = {}
+    headers['X-Auth-Token'] = token
     if full_listing:
         rv = get_container(url, token, container, marker, limit, prefix,
                            delimiter, end_marker, path, http_conn,
-                           service_token)
+                           service_token, headers=headers)
         listing = rv[1]
         while listing:
             if not delimiter:
@@ -674,7 +679,8 @@ def get_container(url, token, container, marker=None, limit=None,
                 marker = listing[-1].get('name', listing[-1].get('subdir'))
             listing = get_container(url, token, container, marker, limit,
                                     prefix, delimiter, end_marker, path,
-                                    http_conn, service_token)[1]
+                                    http_conn, service_token,
+                                    headers=headers)[1]
             if listing:
                 rv[1].extend(listing)
         return rv
@@ -693,7 +699,6 @@ def get_container(url, token, container, marker=None, limit=None,
         qs += '&end_marker=%s' % quote(end_marker)
     if path:
         qs += '&path=%s' % quote(path)
-    headers = {'X-Auth-Token': token}
     if service_token:
         headers['X-Service-Token'] = service_token
     method = 'GET'
@@ -958,7 +963,7 @@ def get_object(url, token, container, name, http_conn=None,
 
 
 def head_object(url, token, container, name, http_conn=None,
-                service_token=None):
+                service_token=None, headers=None):
     """
     Get object info
 
@@ -978,8 +983,12 @@ def head_object(url, token, container, name, http_conn=None,
     else:
         parsed, conn = http_connection(url)
     path = '%s/%s/%s' % (parsed.path, quote(container), quote(name))
+    if headers:
+        headers = dict(headers)
+    else:
+        headers = {}
+    headers['X-Auth-Token'] = token
     method = 'HEAD'
-    headers = {'X-Auth-Token': token}
     if service_token:
         headers['X-Service-Token'] = service_token
     conn.request(method, path, '', headers)
@@ -1450,7 +1459,7 @@ class Connection(object):
 
     def get_container(self, container, marker=None, limit=None, prefix=None,
                       delimiter=None, end_marker=None, path=None,
-                      full_listing=False):
+                      full_listing=False, headers=None):
         """Wrapper for :func:`get_container`"""
         # TODO(unknown): With full_listing=True this will restart the entire
         # listing with each retry. Need to make a better version that just
@@ -1458,7 +1467,7 @@ class Connection(object):
         return self._retry(None, get_container, container, marker=marker,
                            limit=limit, prefix=prefix, delimiter=delimiter,
                            end_marker=end_marker, path=path,
-                           full_listing=full_listing)
+                           full_listing=full_listing, headers=headers)
 
     def put_container(self, container, headers=None, response_dict=None):
         """Wrapper for :func:`put_container`"""
diff --git a/tests/unit/test_swiftclient.py b/tests/unit/test_swiftclient.py
index 23b31388..410fd6f5 100644
--- a/tests/unit/test_swiftclient.py
+++ b/tests/unit/test_swiftclient.py
@@ -600,6 +600,20 @@ class TestGetContainer(MockHttpTest):
         c.get_container('http://www.test.com', 'asdf', 'asdf',
                         path='asdf')
 
+    def test_request_headers(self):
+        c.http_connection = self.fake_http_connection(
+            204, query_string="format=json")
+        conn = c.http_connection('http://www.test.com')
+        headers = {'x-client-key': 'client key'}
+        c.get_container('url_is_irrelevant', 'TOKEN', 'container',
+                        http_conn=conn, headers=headers)
+        self.assertRequests([
+            ('GET', '/container?format=json', '', {
+                'x-auth-token': 'TOKEN',
+                'x-client-key': 'client key',
+            }),
+        ])
+
 
 class TestHeadContainer(MockHttpTest):
 
@@ -729,6 +743,19 @@ class TestHeadObject(MockHttpTest):
         self.assertRaises(c.ClientException, c.head_object,
                           'http://www.test.com', 'asdf', 'asdf', 'asdf')
 
+    def test_request_headers(self):
+        c.http_connection = self.fake_http_connection(204)
+        conn = c.http_connection('http://www.test.com')
+        headers = {'x-client-key': 'client key'}
+        c.head_object('url_is_irrelevant', 'TOKEN', 'container',
+                      'asdf', http_conn=conn, headers=headers)
+        self.assertRequests([
+            ('HEAD', '/container/asdf', '', {
+                'x-auth-token': 'TOKEN',
+                'x-client-key': 'client key',
+            }),
+        ])
+
 
 class TestPutObject(MockHttpTest):