comparison mercurial/httprepo.py @ 2568:52ce0d6bc375

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.
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Thu, 06 Jul 2006 03:14:55 -0300
parents 1727ff712a4e
children ffb895f16925
comparison
equal deleted inserted replaced
2567:2748253b49c2 2568:52ce0d6bc375
85 # if auth required, some data sent twice, so rewind here 85 # if auth required, some data sent twice, so rewind here
86 data.seek(0) 86 data.seek(0)
87 for chunk in util.filechunkiter(data): 87 for chunk in util.filechunkiter(data):
88 keepalive.HTTPConnection.send(self, chunk) 88 keepalive.HTTPConnection.send(self, chunk)
89 89
90 class httphandler(keepalive.HTTPHandler): 90 class basehttphandler(keepalive.HTTPHandler):
91 def http_open(self, req): 91 def http_open(self, req):
92 return self.do_open(httpconnection, req) 92 return self.do_open(httpconnection, req)
93 93
94 class httpsconnection(httplib.HTTPSConnection): 94 has_https = hasattr(urllib2, 'HTTPSHandler')
95 # must be able to send big bundle as stream. 95 if has_https:
96 96 class httpsconnection(httplib.HTTPSConnection):
97 def send(self, data): 97 response_class = keepalive.HTTPResponse
98 if isinstance(data, str): 98 # must be able to send big bundle as stream.
99 httplib.HTTPSConnection.send(self, data) 99
100 else: 100 def send(self, data):
101 # if auth required, some data sent twice, so rewind here 101 if isinstance(data, str):
102 data.seek(0) 102 httplib.HTTPSConnection.send(self, data)
103 for chunk in util.filechunkiter(data): 103 else:
104 httplib.HTTPSConnection.send(self, chunk) 104 # if auth required, some data sent twice, so rewind here
105 105 data.seek(0)
106 class httpshandler(urllib2.HTTPSHandler): 106 for chunk in util.filechunkiter(data):
107 def https_open(self, req): 107 httplib.HTTPSConnection.send(self, chunk)
108 return self.do_open(httpsconnection, req) 108
109 class httphandler(basehttphandler, urllib2.HTTPSHandler):
110 def https_open(self, req):
111 return self.do_open(httpsconnection, req)
112 else:
113 class httphandler(basehttphandler):
114 pass
109 115
110 class httprepository(remoterepository): 116 class httprepository(remoterepository):
111 def __init__(self, ui, path): 117 def __init__(self, ui, path):
112 self.caps = None 118 self.caps = None
113 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path) 119 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
174 (user, passwd and '*' * len(passwd) or 'not set')) 180 (user, passwd and '*' * len(passwd) or 'not set'))
175 passmgr.add_password(None, host, user, passwd or '') 181 passmgr.add_password(None, host, user, passwd or '')
176 182
177 opener = urllib2.build_opener( 183 opener = urllib2.build_opener(
178 handler, 184 handler,
179 httpshandler(),
180 urllib2.HTTPBasicAuthHandler(passmgr), 185 urllib2.HTTPBasicAuthHandler(passmgr),
181 urllib2.HTTPDigestAuthHandler(passmgr)) 186 urllib2.HTTPDigestAuthHandler(passmgr))
182 187
183 # 1.0 here is the _protocol_ version 188 # 1.0 here is the _protocol_ version
184 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')] 189 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
320 finally: 325 finally:
321 fp.close() 326 fp.close()
322 os.unlink(tempname) 327 os.unlink(tempname)
323 328
324 class httpsrepository(httprepository): 329 class httpsrepository(httprepository):
325 pass 330 def __init__(self, ui, path):
331 if not has_https:
332 raise util.Abort(_('Python support for SSL and HTTPS '
333 'is not installed'))
334 httprepository.__init__(self, ui, path)