From 4f3d6e7f3af0c518d7a55b930947a6fbd5b0a5ae Mon Sep 17 00:00:00 2001
From: John Dickinson <me@not.mn>
Date: Fri, 28 Mar 2014 15:45:37 -0700
Subject: [PATCH] set user-agent header

Change-Id: Ia67807667b4b5177d83cce9fcf16d98dc5024fbc
---
 swiftclient/client.py     | 18 +++++++++++++++--
 tests/test_swiftclient.py | 42 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/swiftclient/client.py b/swiftclient/client.py
index ad778175..c5b9a24a 100644
--- a/swiftclient/client.py
+++ b/swiftclient/client.py
@@ -29,6 +29,7 @@ from urllib import quote as _quote
 from urlparse import urlparse, urlunparse
 from time import sleep, time
 
+from swiftclient import version as swiftclient_version
 from swiftclient.exceptions import ClientException, InvalidHeadersException
 from swiftclient.utils import LengthWrapper
 
@@ -133,7 +134,7 @@ except ImportError:
 
 class HTTPConnection:
     def __init__(self, url, proxy=None, cacert=None, insecure=False,
-                 ssl_compression=False):
+                 ssl_compression=False, default_user_agent=None):
         """
         Make an HTTPConnection or HTTPSConnection
 
@@ -147,6 +148,12 @@ class HTTPConnection:
         :param ssl_compression: SSL compression should be disabled by default
                                 and this setting is not usable as of now. The
                                 parameter is kept for backward compatibility.
+        :param default_user_agent: Set the User-Agent header on every request.
+                                   If set to None (default), the user agent
+                                   will be "python-swiftclient-<version>". This
+                                   may be overridden on a per-request basis by
+                                   explicitly setting the user-agent header on
+                                   a call to request().
         :raises ClientException: Unable to handle protocol scheme
         """
         self.url = url
@@ -171,6 +178,10 @@ class HTTPConnection:
                 )
             }
         self.requests_args['stream'] = True
+        if default_user_agent is None:
+            default_user_agent = \
+                'python-swiftclient-%s' % swiftclient_version.version_string
+        self.default_user_agent = default_user_agent
 
     def _request(self, *arg, **kwarg):
         """ Final wrapper before requests call, to be patched in tests """
@@ -178,8 +189,11 @@ class HTTPConnection:
 
     def request(self, method, full_path, data=None, headers={}, files=None):
         """ Encode url and header, then call requests.request """
-        headers = dict((encode_utf8(x), encode_utf8(y)) for x, y in
+        headers = dict((encode_utf8(x.lower()), encode_utf8(y)) for x, y in
                        headers.items())
+        # set a default User-Agent header if it wasn't passed in
+        if 'user-agent' not in headers:
+            headers['user-agent'] = self.default_user_agent
         url = encode_utf8("%s://%s%s" % (
             self.parsed_url.scheme,
             self.parsed_url.netloc,
diff --git a/tests/test_swiftclient.py b/tests/test_swiftclient.py
index 8f709472..552ca0f0 100644
--- a/tests/test_swiftclient.py
+++ b/tests/test_swiftclient.py
@@ -191,6 +191,48 @@ class TestHttpHelpers(MockHttpTest):
         url = 'ftp://www.test.com'
         self.assertRaises(c.ClientException, c.http_connection, url)
 
+    def test_set_user_agent_default(self):
+        _junk, conn = c.http_connection('http://www.example.com')
+        req_headers = {}
+
+        def my_request_handler(*a, **kw):
+            req_headers.update(kw.get('headers', {}))
+        conn._request = my_request_handler
+
+        # test the default
+        conn.request('GET', '/')
+        ua = req_headers.get('user-agent', 'XXX-MISSING-XXX')
+        self.assert_(ua.startswith('python-swiftclient-'))
+
+    def test_set_user_agent_per_request_override(self):
+        _junk, conn = c.http_connection('http://www.example.com')
+        req_headers = {}
+
+        def my_request_handler(*a, **kw):
+            req_headers.update(kw.get('headers', {}))
+        conn._request = my_request_handler
+
+        # test if it's actually set
+        conn.request('GET', '/', headers={'User-Agent': 'Me'})
+        ua = req_headers.get('user-agent', 'XXX-MISSING-XXX')
+        self.assertEqual(ua, 'Me', req_headers)
+
+    def test_set_user_agent_default_override(self):
+        _junk, conn = c.http_connection(
+            'http://www.example.com',
+            default_user_agent='a-new-default')
+        req_headers = {}
+
+        def my_request_handler(*a, **kw):
+            req_headers.update(kw.get('headers', {}))
+        conn._request = my_request_handler
+
+        # test setting a default
+        conn._request = my_request_handler
+        conn.request('GET', '/')
+        ua = req_headers.get('user-agent', 'XXX-MISSING-XXX')
+        self.assertEqual(ua, 'a-new-default')
+
     def test_validate_headers(self):
         headers = {'key': 'value'}
         self.assertEqual(c.validate_headers(headers), None)