Mercurial > public > mercurial-scm > hg
comparison mercurial/httprepo.py @ 2569: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 | 2569: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) |