Mercurial > hg
annotate mercurial/httpconnection.py @ 14517:5a931246afc5
test-copy2: add case for moving a missing file
author | Adrian Buehlmann <adrian@cadifra.com> |
---|---|
date | Thu, 02 Jun 2011 19:43:17 +0200 |
parents | c864f5e743ef |
children | 4a43e23b8c55 |
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 |
14430
c864f5e743ef
httprepo: handle large lengths by bypassing the len() operator
Matt Mackall <mpm@selenic.com>
parents:
14375
diff
changeset
|
40 self._total = self._len / 1024 * 2 |
14244
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 |
14375
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
110 LOGFMT = '%(levelname)s:%(name)s:%(lineno)d:%(message)s' |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
111 # 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
|
112 # 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
|
113 # them. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
114 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
|
115 def __init__(self, ui, pwmgr): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
116 global _configuredlogging |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
117 urllib2.AbstractHTTPHandler.__init__(self) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
118 self.ui = ui |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
119 self.pwmgr = pwmgr |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
120 self._connections = {} |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
121 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
|
122 if loglevel and not _configuredlogging: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
123 _configuredlogging = True |
14294
84256ba2fbf7
httpconnection: fix debug logging option for httpclient
Augie Fackler <durin42@gmail.com>
parents:
14244
diff
changeset
|
124 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
|
125 logger.setLevel(getattr(logging, loglevel.upper())) |
14375
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
126 handler = logging.StreamHandler() |
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
127 handler.setFormatter(logging.Formatter(LOGFMT)) |
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
128 logger.addHandler(handler) |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
129 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
130 def close_all(self): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
131 """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
|
132 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
|
133 for conn in openconns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
134 conn.close() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
135 self._connections = {} |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
136 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
137 # shamelessly borrowed from urllib2.AbstractHTTPHandler |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
138 def do_open(self, http_class, req, use_ssl): |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
139 """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
|
140 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
141 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
|
142 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
|
143 has methods and attributes including: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
144 - 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
|
145 - 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
|
146 - code: HTTP status code |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
147 """ |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
148 # 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
|
149 # 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
|
150 # 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
|
151 # 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
|
152 # attribute which has no accessor. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
153 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
|
154 host = req.get_host() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
155 if tunhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
156 proxyhost = host |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
157 host = tunhost |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
158 elif req.has_proxy(): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
159 proxyhost = req.get_host() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
160 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
|
161 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
162 proxyhost = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
163 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
164 if proxyhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
165 if ':' in proxyhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
166 # 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
|
167 # 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
|
168 # 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
|
169 proxyhost, proxyport = proxyhost.rsplit(':', 1) |
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 proxyport = 3128 # squid default |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
172 proxy = (proxyhost, proxyport) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
173 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
174 proxy = None |
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 if not host: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
177 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
|
178 |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
179 connkey = use_ssl, host, proxy |
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
180 allconns = self._connections.get(connkey, []) |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
181 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
|
182 if conns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
183 h = conns[0] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
184 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
185 if allconns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
186 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
|
187 'one\n' % host) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
188 timeout = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
189 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
|
190 timeout = req.timeout |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
191 h = http_class(host, timeout=timeout, proxy_hostport=proxy) |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
192 self._connections.setdefault(connkey, []).append(h) |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
193 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
194 headers = dict(req.headers) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
195 headers.update(req.unredirected_hdrs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
196 headers = dict( |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
197 (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
|
198 try: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
199 path = req.get_selector() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
200 if '://' in path: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
201 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
|
202 if path[0] != '/': |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
203 path = '/' + path |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
204 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
|
205 r = h.getresponse() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
206 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
|
207 raise urllib2.URLError(err) |
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 # 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
|
210 # object initialized properly. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
211 r.recv = r.read |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
212 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
213 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
|
214 resp.code = r.status |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
215 resp.msg = r.reason |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
216 return resp |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
217 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
218 # 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
|
219 # 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
|
220 # 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
|
221 def http_open(self, req): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
222 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
|
223 return self.https_open(req) |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
224 return self.do_open(HTTPConnection, req, False) |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
225 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
226 def https_open(self, req): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
227 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
|
228 if res: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
229 group, auth = res |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
230 self.auth = auth |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
231 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
|
232 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
233 self.auth = None |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
234 return self.do_open(self._makesslconnection, req, True) |
14244
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 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
|
237 keyfile = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
238 certfile = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
239 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
240 if args: # key_file |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
241 keyfile = args.pop(0) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
242 if args: # cert_file |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
243 certfile = args.pop(0) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
244 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
245 # 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
|
246 # hgrc, we prefer these |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
247 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
|
248 keyfile = self.auth['key'] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
249 certfile = self.auth['cert'] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
250 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
251 # let host port take precedence |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
252 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
|
253 host, port = host.rsplit(':', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
254 port = int(port) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
255 if '[' in host: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
256 host = host[1:-1] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
257 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
258 if keyfile: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
259 kwargs['keyfile'] = keyfile |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
260 if certfile: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
261 kwargs['certfile'] = certfile |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
262 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
263 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
|
264 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
265 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
|
266 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
|
267 **kwargs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
268 return con |