[PATCH] httpconnection: correctly handle redirects from http to https

Augie Fackler durin42 at gmail.com
Mon May 16 17:03:55 CDT 2011


# HG changeset patch
# User Augie Fackler <durin42 at gmail.com>
# Date 1305583185 18000
# Node ID a3a4f7d0c8bdb86033abf36409c43448f3dba761
# Parent  08dbfb626157063647c7c5b77d31ff0a5b849f21
httpconnection: correctly handle redirects from http to https

Previously the connection cache for keepalives didn't keep track of
ssl. This meant that when we connected to an https server after that
same server via http, both on the default port, we'd incorrectly reuse
the non-https connection as the default port meant the connection
cache key was the same.

diff --git a/mercurial/httpconnection.py b/mercurial/httpconnection.py
--- a/mercurial/httpconnection.py
+++ b/mercurial/httpconnection.py
@@ -132,7 +132,7 @@
         self._connections = {}
 
     # shamelessly borrowed from urllib2.AbstractHTTPHandler
-    def do_open(self, http_class, req):
+    def do_open(self, http_class, req, use_ssl):
         """Return an addinfourl object for the request, using http_class.
 
         http_class must implement the HTTPConnection API from httplib.
@@ -173,7 +173,8 @@
         if not host:
             raise urllib2.URLError('no host given')
 
-        allconns = self._connections.get((host, proxy), [])
+        connkey = use_ssl, host, proxy
+        allconns = self._connections.get(connkey, [])
         conns = [c for c in allconns if not c.busy()]
         if conns:
             h = conns[0]
@@ -185,7 +186,7 @@
             if req.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                 timeout = req.timeout
             h = http_class(host, timeout=timeout, proxy_hostport=proxy)
-            self._connections.setdefault((host, proxy), []).append(h)
+            self._connections.setdefault(connkey, []).append(h)
 
         headers = dict(req.headers)
         headers.update(req.unredirected_hdrs)
@@ -217,7 +218,7 @@
     def http_open(self, req):
         if req.get_full_url().startswith('https'):
             return self.https_open(req)
-        return self.do_open(HTTPConnection, req)
+        return self.do_open(HTTPConnection, req, False)
 
     def https_open(self, req):
         res = readauthforuri(self.ui, req.get_full_url())
@@ -227,7 +228,7 @@
             self.ui.debug("using auth.%s.* for authentication\n" % group)
         else:
             self.auth = None
-        return self.do_open(self._makesslconnection, req)
+        return self.do_open(self._makesslconnection, req, True)
 
     def _makesslconnection(self, host, port=443, *args, **kwargs):
         keyfile = None


More information about the Mercurial-devel mailing list