httprepo: factor out proxy handling
authorBenoit Boissinot <benoit.boissinot@ens-lyon.org>
Mon, 27 Oct 2008 17:48:05 +0100
changeset 7269 95a53961d7a6
parent 7264 7e963c80bbe6
child 7270 2db33c1a5654
httprepo: factor out proxy handling
mercurial/httprepo.py
tests/test-http-proxy
tests/test-http-proxy.out
--- a/mercurial/httprepo.py	Mon Oct 27 17:37:37 2008 +0100
+++ b/mercurial/httprepo.py	Mon Oct 27 17:48:05 2008 +0100
@@ -39,6 +39,66 @@
         self.add_password(realm, authuri, user, passwd)
         return (user, passwd)
 
+class proxyhandler(urllib2.ProxyHandler):
+    def __init__(self, ui):
+        proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
+        # XXX proxyauthinfo = None
+
+        if proxyurl:
+            # proxy can be proper url or host[:port]
+            if not (proxyurl.startswith('http:') or
+                    proxyurl.startswith('https:')):
+                proxyurl = 'http://' + proxyurl + '/'
+            snpqf = urlparse.urlsplit(proxyurl)
+            proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
+            hpup = netlocsplit(proxynetloc)
+
+            proxyhost, proxyport, proxyuser, proxypasswd = hpup
+            if not proxyuser:
+                proxyuser = ui.config("http_proxy", "user")
+                proxypasswd = ui.config("http_proxy", "passwd")
+
+            # see if we should use a proxy for this url
+            no_list = [ "localhost", "127.0.0.1" ]
+            no_list.extend([p.lower() for
+                            p in ui.configlist("http_proxy", "no")])
+            no_list.extend([p.strip().lower() for
+                            p in os.getenv("no_proxy", '').split(',')
+                            if p.strip()])
+            # "http_proxy.always" config is for running tests on localhost
+            if ui.configbool("http_proxy", "always"):
+                self.no_list = []
+            else:
+                self.no_list = no_list
+
+            proxyurl = urlparse.urlunsplit((
+                proxyscheme, netlocunsplit(proxyhost, proxyport,
+                                           proxyuser, proxypasswd or ''),
+                proxypath, proxyquery, proxyfrag))
+            proxies = {'http': proxyurl, 'https': proxyurl}
+            ui.debug(_('proxying through http://%s:%s\n') %
+                      (proxyhost, proxyport))
+        else:
+            proxies = {}
+
+        # urllib2 takes proxy values from the environment and those
+        # will take precedence if found, so drop them
+        for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
+            try:
+                if env in os.environ:
+                    del os.environ[env]
+            except OSError:
+                pass
+
+        urllib2.ProxyHandler.__init__(self, proxies)
+        self.ui = ui
+
+    def proxy_open(self, req, proxy, type):
+        host = req.get_host().split(':')[0]
+        if host in self.no_list:
+            return None
+        return urllib2.ProxyHandler.proxy_open(self, req, proxy, type)
+
 def netlocsplit(netloc):
     '''split [user[:passwd]@]host[:port] into 4-tuple.'''
 
@@ -200,57 +260,11 @@
         self.ui = ui
         self.ui.debug(_('using %s\n') % self._url)
 
-        proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
-        # XXX proxyauthinfo = None
         handlers = [httphandler()]
         if has_https:
             handlers.append(httpshandler())
 
-        if proxyurl:
-            # proxy can be proper url or host[:port]
-            if not (proxyurl.startswith('http:') or
-                    proxyurl.startswith('https:')):
-                proxyurl = 'http://' + proxyurl + '/'
-            snpqf = urlparse.urlsplit(proxyurl)
-            proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
-            hpup = netlocsplit(proxynetloc)
-
-            proxyhost, proxyport, proxyuser, proxypasswd = hpup
-            if not proxyuser:
-                proxyuser = ui.config("http_proxy", "user")
-                proxypasswd = ui.config("http_proxy", "passwd")
-
-            # see if we should use a proxy for this url
-            no_list = [ "localhost", "127.0.0.1" ]
-            no_list.extend([p.lower() for
-                            p in ui.configlist("http_proxy", "no")])
-            no_list.extend([p.strip().lower() for
-                            p in os.getenv("no_proxy", '').split(',')
-                            if p.strip()])
-            # "http_proxy.always" config is for running tests on localhost
-            if (not ui.configbool("http_proxy", "always") and
-                host.lower() in no_list):
-                # avoid auto-detection of proxy settings by appending
-                # a ProxyHandler with no proxies defined.
-                handlers.append(urllib2.ProxyHandler({}))
-                ui.debug(_('disabling proxy for %s\n') % host)
-            else:
-                proxyurl = urlparse.urlunsplit((
-                    proxyscheme, netlocunsplit(proxyhost, proxyport,
-                                               proxyuser, proxypasswd or ''),
-                    proxypath, proxyquery, proxyfrag))
-                handlers.append(urllib2.ProxyHandler({scheme: proxyurl}))
-                ui.debug(_('proxying through http://%s:%s\n') %
-                          (proxyhost, proxyport))
-
-        # urllib2 takes proxy values from the environment and those
-        # will take precedence if found, so drop them
-        for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
-            try:
-                if env in os.environ:
-                    del os.environ[env]
-            except OSError:
-                pass
+        handlers.append(proxyhandler(ui))
 
         passmgr = passwordmgr(ui)
         if user:
--- a/tests/test-http-proxy	Mon Oct 27 17:37:37 2008 +0100
+++ b/tests/test-http-proxy	Mon Oct 27 17:48:05 2008 +0100
@@ -38,5 +38,8 @@
 echo %% bad host:port for proxy
 http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f
 
+echo %% do not use the proxy if it is in the no list
+http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.no=localhost http://localhost:$HGPORT/ g
+
 cat proxy.log | sed -e 's/^.*\] /XXX /'
 exit 0
--- a/tests/test-http-proxy.out	Mon Oct 27 17:37:37 2008 +0100
+++ b/tests/test-http-proxy.out	Mon Oct 27 17:48:05 2008 +0100
@@ -49,6 +49,14 @@
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 %% bad host:port for proxy
 abort: error: Connection refused
+%% do not use the proxy if it is in the no list
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+updating working directory
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 XXX "GET http://localhost:20059/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
 XXX "GET http://localhost:20059/?cmd=capabilities HTTP/1.1" - -
 XXX "GET http://localhost:20059/?cmd=stream_out HTTP/1.1" - -