HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available
authorAlexis S. L. Carvalho <alexis@cecm.usp.br>
Thu, 06 Jul 2006 03:14:55 -0300
changeset 2569 52ce0d6bc375
parent 2567 2748253b49c2
child 2570 2264b2b077a1
HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available The urllib2 differences between python 2.3 and 2.4 are hidden by using keepalive.py, which also gives us support for persistent connections. Support for HTTPS is enabled only if there's a HTTPSHandler class in urllib2. It's not possible to have separate classes as handlers for HTTP and HTTPS: to support persistent HTTPS connections, we need a class that inherits from both keepalive.HTTPHandler and urllib2.HTTPSHandler. If we try to pass (an instance of) this class and (an instance of) the httphandler class to urllib2.build_opener, this function ends up getting confused, since both classes are subclasses of the HTTPHandler default handler, and raises an exception.
mercurial/httprepo.py
--- a/mercurial/httprepo.py	Wed Jul 05 13:28:25 2006 -0500
+++ b/mercurial/httprepo.py	Thu Jul 06 03:14:55 2006 -0300
@@ -87,25 +87,31 @@
             for chunk in util.filechunkiter(data):
                 keepalive.HTTPConnection.send(self, chunk)
 
-class httphandler(keepalive.HTTPHandler):
+class basehttphandler(keepalive.HTTPHandler):
     def http_open(self, req):
         return self.do_open(httpconnection, req)
 
-class httpsconnection(httplib.HTTPSConnection):
-    # must be able to send big bundle as stream.
+has_https = hasattr(urllib2, 'HTTPSHandler')
+if has_https:
+    class httpsconnection(httplib.HTTPSConnection):
+        response_class = keepalive.HTTPResponse
+        # must be able to send big bundle as stream.
 
-    def send(self, data):
-        if isinstance(data, str):
-            httplib.HTTPSConnection.send(self, data)
-        else:
-            # if auth required, some data sent twice, so rewind here
-            data.seek(0)
-            for chunk in util.filechunkiter(data):
-                httplib.HTTPSConnection.send(self, chunk)
+        def send(self, data):
+            if isinstance(data, str):
+                httplib.HTTPSConnection.send(self, data)
+            else:
+                # if auth required, some data sent twice, so rewind here
+                data.seek(0)
+                for chunk in util.filechunkiter(data):
+                    httplib.HTTPSConnection.send(self, chunk)
 
-class httpshandler(urllib2.HTTPSHandler):
-    def https_open(self, req):
-        return self.do_open(httpsconnection, req)
+    class httphandler(basehttphandler, urllib2.HTTPSHandler):
+        def https_open(self, req):
+            return self.do_open(httpsconnection, req)
+else:
+    class httphandler(basehttphandler):
+        pass
 
 class httprepository(remoterepository):
     def __init__(self, ui, path):
@@ -176,7 +182,6 @@
 
         opener = urllib2.build_opener(
             handler,
-            httpshandler(),
             urllib2.HTTPBasicAuthHandler(passmgr),
             urllib2.HTTPDigestAuthHandler(passmgr))
 
@@ -322,4 +327,8 @@
             os.unlink(tempname)
 
 class httpsrepository(httprepository):
-    pass
+    def __init__(self, ui, path):
+        if not has_https:
+            raise util.Abort(_('Python support for SSL and HTTPS '
+                               'is not installed'))
+        httprepository.__init__(self, ui, path)