[ Vincent Bernat ]
> OoO Pendant  le journal télévisé du  lundi 21 janvier  2008, vers 20:40,
> Eric Evans <[EMAIL PROTECTED]> disait:
> > [ Vincent Bernat ]
> >> Proxy support using http_proxy environment variable seems broken. Boto
> >> seems to wait http_proxy as "proxy:port", while the form of this
> >> variable is usually "http://proxy:port";. Since it splits on ":", it
> >> gets a 3-tuple instead of a 2-tuple.
> >> 
> >> Moreover, this variable can be empty. In this case, we get an
> >> exception because Boto tries to access to
> >> os.environ['http_proxy'].split(':')[1].
> 
> > I've submitted a bug upstream[1] and included the attached patch.
> 
> > If you have the opportunity to try out the patch, please update the bug
> > report and let me know if there are any problems.
> 
> Hi Éric !
> 
> I   will   try   to   complete   your  patch   for   a   more   complete
> support.    http_proxy     can    also    be    of     the    form    of
> http://user:[EMAIL PROTECTED]:port.  In  this  case,  your patch  does  not
> work.  Maybe there  is some  code in  urllib to  correctly parse  such a
> variable.

Hi Vincent,

There are some parsing functions in urllib and urlparse but none of them
seemed to provide for a very clean solution.

The attached patch should correctly parse urls with or without a
username/password pair as well as setting up the appropriate header for
proxy basic auth.

Again, I don't have a ready means of testing this. I've made sure that
it's parsing the url and setting the instance attributes correctly, and
that it doesn't effect normal usage of boto. If you could apply the
patch and let me know how it works for you, it would be appreciated.

Thanks again,

-- 
Eric Evans
[EMAIL PROTECTED]
Index: boto/connection.py
===================================================================
--- boto.orig/connection.py     2008-01-21 10:58:59.000000000 -0600
+++ boto/connection.py  2008-01-29 15:05:43.000000000 -0600
@@ -55,9 +55,13 @@
 class AWSAuthConnection:
     def __init__(self, server, aws_access_key_id=None,
                  aws_secret_access_key=None, is_secure=True, port=None,
-                 proxy=None, proxy_port=None, debug=False,
-                 https_connection_factory=None):
+                 proxy=None, proxy_port=None, proxy_user=None,
+                 proxy_pass=None, debug=False, https_connection_factory=None):
         self.is_secure = is_secure
+        self.proxy = proxy
+        self.proxy_port = proxy_port
+        self.proxy_user = proxy_user
+        self.proxy_pass = proxy_pass
         # define exceptions from httplib that we want to catch and retry
         self.http_exceptions = (httplib.HTTPException, socket.error, 
socket.gaierror)
         # define values in socket exceptions we don't want to catch
@@ -90,29 +94,31 @@
             if os.environ.has_key('AWS_SECRET_ACCESS_KEY'):
                 self.aws_secret_access_key = 
os.environ['AWS_SECRET_ACCESS_KEY']
         
-        self.proxy = proxy
         #This lowercase environment var is the same as used in urllib
-        if os.environ.has_key('http_proxy'): 
-            proxy_port_pair = os.environ['http_proxy'].split(':')
-            self.proxy = proxy_port_pair[0]
+        if os.environ.has_key('http_proxy') and not self.proxy:
+            pattern = re.compile(
+                '(?:http://)?' \
+                '(?:(?P<user>\w+):(?P<pass>\w+)@)?' \
+                '(?P<host>[\w\-\.]+)' \
+                '(?::(?P<port>\d+))?'
+            )
+            match = pattern.match(os.environ['http_proxy'])
+            if match:
+                self.proxy = match.group('host')
+                self.proxy_port = match.group('port')
+                self.proxy_user = match.group('user')
+                self.proxy_pass = match.group('pass')
+
+                if not self.proxy_port and self.proxy:
+                    print "http_proxy environment variable does not specify " \
+                                "a port, using default"
+                    self.proxy_port = self.port
+
             
         self.use_proxy = (self.proxy != None)
         if (self.use_proxy and self.is_secure):
             raise AWSConnectionError("Unable to provide secure connection 
through proxy")
         
-        if proxy_port:
-            self.proxy_port = proxy_port
-        else:
-            if os.environ.has_key('http_proxy'):
-                proxy_port_pair = os.environ['http_proxy'].split(':')[1]
-                if len(proxy_port_pair) != 2:
-                    print "http_proxy env var does not specify port, using 
default"
-                    self.proxy_port = self.port
-                else:
-                    self.proxy_port = proxy_port_pair[1]
-            else:
-                self.proxy_port = None
-        
         self.make_http_connection()
         self._last_rs = None
 
@@ -143,7 +149,11 @@
     def prefix_proxy_to_path(self, path):
         path = self.protocol + '://' + self.server + path
         return path
-        
+
+    def get_proxy_auth_header(self):
+        auth = base64.encodestring(self.proxy_user+':'+self.proxy_pass)
+        return {'Proxy-Authorization': 'Basic %s' % auth}
+
     def make_request(self, method, path, headers=None, data='', metadata=None):
         if headers == None:
             headers = {}
@@ -151,11 +161,13 @@
             metadata = {}
         if not headers.has_key('Content-Length'):
             headers['Content-Length'] = len(data)
+        if self.use_proxy:
+            path = self.prefix_proxy_to_path(path)
+            if self.proxy_user and self.proxy_pass:
+                headers.update(self.get_proxy_auth_header())
         final_headers = boto.utils.merge_meta(headers, metadata);
         # add auth header
         self.add_aws_auth_header(final_headers, method, path)
-        if self.use_proxy:
-            path = self.prefix_proxy_to_path(path)
         try:
             self.connection.request(method, path, data, final_headers)
             return self.connection.getresponse()

Attachment: signature.asc
Description: Digital signature

Reply via email to