Mercurial > hg
annotate mercurial/httpconnection.py @ 14301:f94993769c87
revlog: improve delta generation heuristics for generaldelta
Without this change, pulls (and clones) into a generaldelta repository could
generate very inefficient revlogs, the size of which could be at least twice
the original size.
This was caused by the generated delta chains covering too large distances,
causing new chains to be built far too often. This change addresses the
problem by forcing a delta against second parent or against the previous
revision, when the first parent delta is in danger of creating a long chain.
author | Sune Foldager <cryo@cyanite.org> |
---|---|
date | Thu, 12 May 2011 15:24:33 +0200 |
parents | 84256ba2fbf7 |
children | bf85c2639700 |
rev | line source |
---|---|
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
1 # httpconnection.py - urllib2 handler for new http support |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
2 # |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com> |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br> |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
6 # Copyright 2011 Google, Inc. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
7 # |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
8 # This software may be used and distributed according to the terms of the |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
9 # GNU General Public License version 2 or any later version. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
10 import logging |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
11 import socket |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
12 import urllib |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
13 import urllib2 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
14 import os |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
15 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
16 from mercurial import httpclient |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
17 from mercurial import sslutil |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
18 from mercurial import util |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
19 from mercurial.i18n import _ |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
20 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
21 # moved here from url.py to avoid a cycle |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
22 class httpsendfile(object): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
23 """This is a wrapper around the objects returned by python's "open". |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
24 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
25 Its purpose is to send file-like objects via HTTP and, to do so, it |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
26 defines a __len__ attribute to feed the Content-Length header. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
27 """ |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
28 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
29 def __init__(self, ui, *args, **kwargs): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
30 # We can't just "self._data = open(*args, **kwargs)" here because there |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
31 # is an "open" function defined in this module that shadows the global |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
32 # one |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
33 self.ui = ui |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
34 self._data = open(*args, **kwargs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
35 self.seek = self._data.seek |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
36 self.close = self._data.close |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
37 self.write = self._data.write |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
38 self._len = os.fstat(self._data.fileno()).st_size |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
39 self._pos = 0 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
40 self._total = len(self) / 1024 * 2 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
41 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
42 def read(self, *args, **kwargs): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
43 try: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
44 ret = self._data.read(*args, **kwargs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
45 except EOFError: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
46 self.ui.progress(_('sending'), None) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
47 self._pos += len(ret) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
48 # We pass double the max for total because we currently have |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
49 # to send the bundle twice in the case of a server that |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
50 # requires authentication. Since we can't know until we try |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
51 # once whether authentication will be required, just lie to |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
52 # the user and maybe the push succeeds suddenly at 50%. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
53 self.ui.progress(_('sending'), self._pos / 1024, |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
54 unit=_('kb'), total=self._total) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
55 return ret |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
56 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
57 def __len__(self): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
58 return self._len |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
59 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
60 # moved here from url.py to avoid a cycle |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
61 def readauthforuri(ui, uri): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
62 # Read configuration |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
63 config = dict() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
64 for key, val in ui.configitems('auth'): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
65 if '.' not in key: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
66 ui.warn(_("ignoring invalid [auth] key '%s'\n") % key) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
67 continue |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
68 group, setting = key.rsplit('.', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
69 gdict = config.setdefault(group, dict()) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
70 if setting in ('username', 'cert', 'key'): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
71 val = util.expandpath(val) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
72 gdict[setting] = val |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
73 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
74 # Find the best match |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
75 scheme, hostpath = uri.split('://', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
76 bestlen = 0 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
77 bestauth = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
78 for group, auth in config.iteritems(): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
79 prefix = auth.get('prefix') |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
80 if not prefix: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
81 continue |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
82 p = prefix.split('://', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
83 if len(p) > 1: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
84 schemes, prefix = [p[0]], p[1] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
85 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
86 schemes = (auth.get('schemes') or 'https').split() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
87 if (prefix == '*' or hostpath.startswith(prefix)) and \ |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
88 len(prefix) > bestlen and scheme in schemes: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
89 bestlen = len(prefix) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
90 bestauth = group, auth |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
91 return bestauth |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
92 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
93 # Mercurial (at least until we can remove the old codepath) requires |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
94 # that the http response object be sufficiently file-like, so we |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
95 # provide a close() method here. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
96 class HTTPResponse(httpclient.HTTPResponse): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
97 def close(self): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
98 pass |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
99 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
100 class HTTPConnection(httpclient.HTTPConnection): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
101 response_class = HTTPResponse |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
102 def request(self, method, uri, body=None, headers={}): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
103 if isinstance(body, httpsendfile): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
104 body.seek(0) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
105 httpclient.HTTPConnection.request(self, method, uri, body=body, |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
106 headers=headers) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
107 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
108 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
109 _configuredlogging = False |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
110 # Subclass BOTH of these because otherwise urllib2 "helpfully" |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
111 # reinserts them since it notices we don't include any subclasses of |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
112 # them. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
113 class http2handler(urllib2.HTTPHandler, urllib2.HTTPSHandler): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
114 def __init__(self, ui, pwmgr): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
115 global _configuredlogging |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
116 urllib2.AbstractHTTPHandler.__init__(self) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
117 self.ui = ui |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
118 self.pwmgr = pwmgr |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
119 self._connections = {} |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
120 loglevel = ui.config('ui', 'http2debuglevel', default=None) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
121 if loglevel and not _configuredlogging: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
122 _configuredlogging = True |
14294
84256ba2fbf7
httpconnection: fix debug logging option for httpclient
Augie Fackler <durin42@gmail.com>
parents:
14244
diff
changeset
|
123 logger = logging.getLogger('mercurial.httpclient') |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
124 logger.setLevel(getattr(logging, loglevel.upper())) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
125 logger.addHandler(logging.StreamHandler()) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
126 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
127 def close_all(self): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
128 """Close and remove all connection objects being kept for reuse.""" |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
129 for openconns in self._connections.values(): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
130 for conn in openconns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
131 conn.close() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
132 self._connections = {} |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
133 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
134 # shamelessly borrowed from urllib2.AbstractHTTPHandler |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
135 def do_open(self, http_class, req): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
136 """Return an addinfourl object for the request, using http_class. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
137 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
138 http_class must implement the HTTPConnection API from httplib. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
139 The addinfourl return value is a file-like object. It also |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
140 has methods and attributes including: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
141 - info(): return a mimetools.Message object for the headers |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
142 - geturl(): return the original request URL |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
143 - code: HTTP status code |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
144 """ |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
145 # If using a proxy, the host returned by get_host() is |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
146 # actually the proxy. On Python 2.6.1, the real destination |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
147 # hostname is encoded in the URI in the urllib2 request |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
148 # object. On Python 2.6.5, it's stored in the _tunnel_host |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
149 # attribute which has no accessor. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
150 tunhost = getattr(req, '_tunnel_host', None) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
151 host = req.get_host() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
152 if tunhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
153 proxyhost = host |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
154 host = tunhost |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
155 elif req.has_proxy(): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
156 proxyhost = req.get_host() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
157 host = req.get_selector().split('://', 1)[1].split('/', 1)[0] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
158 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
159 proxyhost = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
160 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
161 if proxyhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
162 if ':' in proxyhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
163 # Note: this means we'll explode if we try and use an |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
164 # IPv6 http proxy. This isn't a regression, so we |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
165 # won't worry about it for now. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
166 proxyhost, proxyport = proxyhost.rsplit(':', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
167 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
168 proxyport = 3128 # squid default |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
169 proxy = (proxyhost, proxyport) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
170 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
171 proxy = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
172 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
173 if not host: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
174 raise urllib2.URLError('no host given') |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
175 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
176 allconns = self._connections.get((host, proxy), []) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
177 conns = [c for c in allconns if not c.busy()] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
178 if conns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
179 h = conns[0] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
180 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
181 if allconns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
182 self.ui.debug('all connections for %s busy, making a new ' |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
183 'one\n' % host) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
184 timeout = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
185 if req.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
186 timeout = req.timeout |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
187 h = http_class(host, timeout=timeout, proxy_hostport=proxy) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
188 self._connections.setdefault((host, proxy), []).append(h) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
189 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
190 headers = dict(req.headers) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
191 headers.update(req.unredirected_hdrs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
192 headers = dict( |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
193 (name.title(), val) for name, val in headers.items()) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
194 try: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
195 path = req.get_selector() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
196 if '://' in path: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
197 path = path.split('://', 1)[1].split('/', 1)[1] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
198 if path[0] != '/': |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
199 path = '/' + path |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
200 h.request(req.get_method(), path, req.data, headers) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
201 r = h.getresponse() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
202 except socket.error, err: # XXX what error? |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
203 raise urllib2.URLError(err) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
204 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
205 # Pick apart the HTTPResponse object to get the addinfourl |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
206 # object initialized properly. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
207 r.recv = r.read |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
208 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
209 resp = urllib.addinfourl(r, r.headers, req.get_full_url()) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
210 resp.code = r.status |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
211 resp.msg = r.reason |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
212 return resp |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
213 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
214 # httplib always uses the given host/port as the socket connect |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
215 # target, and then allows full URIs in the request path, which it |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
216 # then observes and treats as a signal to do proxying instead. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
217 def http_open(self, req): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
218 if req.get_full_url().startswith('https'): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
219 return self.https_open(req) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
220 return self.do_open(HTTPConnection, req) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
221 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
222 def https_open(self, req): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
223 res = readauthforuri(self.ui, req.get_full_url()) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
224 if res: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
225 group, auth = res |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
226 self.auth = auth |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
227 self.ui.debug("using auth.%s.* for authentication\n" % group) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
228 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
229 self.auth = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
230 return self.do_open(self._makesslconnection, req) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
231 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
232 def _makesslconnection(self, host, port=443, *args, **kwargs): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
233 keyfile = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
234 certfile = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
235 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
236 if args: # key_file |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
237 keyfile = args.pop(0) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
238 if args: # cert_file |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
239 certfile = args.pop(0) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
240 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
241 # if the user has specified different key/cert files in |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
242 # hgrc, we prefer these |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
243 if self.auth and 'key' in self.auth and 'cert' in self.auth: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
244 keyfile = self.auth['key'] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
245 certfile = self.auth['cert'] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
246 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
247 # let host port take precedence |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
248 if ':' in host and '[' not in host or ']:' in host: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
249 host, port = host.rsplit(':', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
250 port = int(port) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
251 if '[' in host: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
252 host = host[1:-1] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
253 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
254 if keyfile: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
255 kwargs['keyfile'] = keyfile |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
256 if certfile: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
257 kwargs['certfile'] = certfile |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
258 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
259 kwargs.update(sslutil.sslkwargs(self.ui, host)) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
260 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
261 con = HTTPConnection(host, port, use_ssl=True, |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
262 ssl_validator=sslutil.validator(self.ui, host), |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
263 **kwargs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
264 return con |