Mercurial > hg
annotate mercurial/httpconnection.py @ 17583:55724f42fa14
merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 17 Sep 2012 15:13:17 -0500 |
parents | 72803c8edaa4 |
children | 21503aa02d4f |
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 |
15152
94b200a11cf7
http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents:
15025
diff
changeset
|
25 Its purpose is to send file-like objects via HTTP. |
94b200a11cf7
http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents:
15025
diff
changeset
|
26 It do however not define a __len__ attribute because the length |
94b200a11cf7
http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents:
15025
diff
changeset
|
27 might be more than Py_ssize_t can handle. |
14244
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 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
30 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
|
31 # 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
|
32 # 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
|
33 # one |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
34 self.ui = ui |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
35 self._data = open(*args, **kwargs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
36 self.seek = self._data.seek |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
37 self.close = self._data.close |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
38 self.write = self._data.write |
15152
94b200a11cf7
http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents:
15025
diff
changeset
|
39 self.length = os.fstat(self._data.fileno()).st_size |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
40 self._pos = 0 |
15791
a814f8fcc65a
Use explicit integer division
Martin Geisler <mg@aragost.com>
parents:
15288
diff
changeset
|
41 self._total = self.length // 1024 * 2 |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
42 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
43 def read(self, *args, **kwargs): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
44 try: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
45 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
|
46 except EOFError: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
47 self.ui.progress(_('sending'), None) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
48 self._pos += len(ret) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
49 # 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
|
50 # 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
|
51 # 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
|
52 # 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
|
53 # the user and maybe the push succeeds suddenly at 50%. |
15791
a814f8fcc65a
Use explicit integer division
Martin Geisler <mg@aragost.com>
parents:
15288
diff
changeset
|
54 self.ui.progress(_('sending'), self._pos // 1024, |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
55 unit=_('kb'), total=self._total) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
56 return ret |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
57 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
58 # moved here from url.py to avoid a cycle |
15025
0593e8f81c71
http: pass user to readauthforuri() (fix 4a43e23b8c55)
Patrick Mezard <pmezard@gmail.com>
parents:
15005
diff
changeset
|
59 def readauthforuri(ui, uri, user): |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
60 # Read configuration |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
61 config = dict() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
62 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
|
63 if '.' not in key: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
64 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
|
65 continue |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
66 group, setting = key.rsplit('.', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
67 gdict = config.setdefault(group, dict()) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
68 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
|
69 val = util.expandpath(val) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
70 gdict[setting] = val |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
71 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
72 # Find the best match |
15288
b3083042bdda
auth: fix realm handling with Python < 2.4.3 (issue2739)
Matt Mackall <mpm@selenic.com>
parents:
15152
diff
changeset
|
73 if '://' in uri: |
b3083042bdda
auth: fix realm handling with Python < 2.4.3 (issue2739)
Matt Mackall <mpm@selenic.com>
parents:
15152
diff
changeset
|
74 scheme, hostpath = uri.split('://', 1) |
b3083042bdda
auth: fix realm handling with Python < 2.4.3 (issue2739)
Matt Mackall <mpm@selenic.com>
parents:
15152
diff
changeset
|
75 else: |
17428
72803c8edaa4
avoid using abbreviations that look like spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents:
15791
diff
changeset
|
76 # Python 2.4.1 doesn't provide the full URI |
15288
b3083042bdda
auth: fix realm handling with Python < 2.4.3 (issue2739)
Matt Mackall <mpm@selenic.com>
parents:
15152
diff
changeset
|
77 scheme, hostpath = 'http', uri |
15005
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
78 bestuser = None |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
79 bestlen = 0 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
80 bestauth = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
81 for group, auth in config.iteritems(): |
15005
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
82 if user and user != auth.get('username', user): |
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
83 # If a username was set in the URI, the entry username |
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
84 # must either match it or be unset |
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
85 continue |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
86 prefix = auth.get('prefix') |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
87 if not prefix: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
88 continue |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
89 p = prefix.split('://', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
90 if len(p) > 1: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
91 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
|
92 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
93 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
|
94 if (prefix == '*' or hostpath.startswith(prefix)) and \ |
15005
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
95 (len(prefix) > bestlen or (len(prefix) == bestlen and \ |
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
96 not bestuser and 'username' in auth)) \ |
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
97 and scheme in schemes: |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
98 bestlen = len(prefix) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
99 bestauth = group, auth |
15005
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
100 bestuser = auth.get('username') |
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
101 if user and not bestuser: |
4a43e23b8c55
hgweb: do not ignore [auth] if url has a username (issue2822)
Patrick Mezard <pmezard@gmail.com>
parents:
14430
diff
changeset
|
102 auth['username'] = user |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
103 return bestauth |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
104 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
105 # 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
|
106 # 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
|
107 # provide a close() method here. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
108 class HTTPResponse(httpclient.HTTPResponse): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
109 def close(self): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
110 pass |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
111 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
112 class HTTPConnection(httpclient.HTTPConnection): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
113 response_class = HTTPResponse |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
114 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
|
115 if isinstance(body, httpsendfile): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
116 body.seek(0) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
117 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
|
118 headers=headers) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
119 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
120 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
121 _configuredlogging = False |
14375
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
122 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
|
123 # 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
|
124 # 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
|
125 # them. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
126 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
|
127 def __init__(self, ui, pwmgr): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
128 global _configuredlogging |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
129 urllib2.AbstractHTTPHandler.__init__(self) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
130 self.ui = ui |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
131 self.pwmgr = pwmgr |
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 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
|
134 if loglevel and not _configuredlogging: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
135 _configuredlogging = True |
14294
84256ba2fbf7
httpconnection: fix debug logging option for httpclient
Augie Fackler <durin42@gmail.com>
parents:
14244
diff
changeset
|
136 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
|
137 logger.setLevel(getattr(logging, loglevel.upper())) |
14375
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
138 handler = logging.StreamHandler() |
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
139 handler.setFormatter(logging.Formatter(LOGFMT)) |
436e5379d7ba
httpconnection: improved logging formatting
Augie Fackler <durin42@gmail.com>
parents:
14346
diff
changeset
|
140 logger.addHandler(handler) |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
141 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
142 def close_all(self): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
143 """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
|
144 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
|
145 for conn in openconns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
146 conn.close() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
147 self._connections = {} |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
148 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
149 # shamelessly borrowed from urllib2.AbstractHTTPHandler |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
150 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
|
151 """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
|
152 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
153 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
|
154 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
|
155 has methods and attributes including: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
156 - 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
|
157 - 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
|
158 - code: HTTP status code |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
159 """ |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
160 # 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
|
161 # 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
|
162 # 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
|
163 # 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
|
164 # attribute which has no accessor. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
165 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
|
166 host = req.get_host() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
167 if tunhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
168 proxyhost = host |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
169 host = tunhost |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
170 elif req.has_proxy(): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
171 proxyhost = req.get_host() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
172 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
|
173 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
174 proxyhost = 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 proxyhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
177 if ':' in proxyhost: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
178 # 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
|
179 # 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
|
180 # 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
|
181 proxyhost, proxyport = proxyhost.rsplit(':', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
182 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
183 proxyport = 3128 # squid default |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
184 proxy = (proxyhost, proxyport) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
185 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
186 proxy = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
187 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
188 if not host: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
189 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
|
190 |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
191 connkey = use_ssl, host, proxy |
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
192 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
|
193 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
|
194 if conns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
195 h = conns[0] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
196 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
197 if allconns: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
198 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
|
199 'one\n' % host) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
200 timeout = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
201 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
|
202 timeout = req.timeout |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
203 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
|
204 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
|
205 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
206 headers = dict(req.headers) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
207 headers.update(req.unredirected_hdrs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
208 headers = dict( |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
209 (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
|
210 try: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
211 path = req.get_selector() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
212 if '://' in path: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
213 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
|
214 if path[0] != '/': |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
215 path = '/' + path |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
216 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
|
217 r = h.getresponse() |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
218 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
|
219 raise urllib2.URLError(err) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
220 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
221 # 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
|
222 # object initialized properly. |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
223 r.recv = r.read |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
224 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
225 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
|
226 resp.code = r.status |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
227 resp.msg = r.reason |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
228 return resp |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
229 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
230 # 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
|
231 # 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
|
232 # 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
|
233 def http_open(self, req): |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
234 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
|
235 return self.https_open(req) |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
236 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
|
237 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
238 def https_open(self, req): |
15025
0593e8f81c71
http: pass user to readauthforuri() (fix 4a43e23b8c55)
Patrick Mezard <pmezard@gmail.com>
parents:
15005
diff
changeset
|
239 # req.get_full_url() does not contain credentials and we may |
0593e8f81c71
http: pass user to readauthforuri() (fix 4a43e23b8c55)
Patrick Mezard <pmezard@gmail.com>
parents:
15005
diff
changeset
|
240 # need them to match the certificates. |
0593e8f81c71
http: pass user to readauthforuri() (fix 4a43e23b8c55)
Patrick Mezard <pmezard@gmail.com>
parents:
15005
diff
changeset
|
241 url = req.get_full_url() |
0593e8f81c71
http: pass user to readauthforuri() (fix 4a43e23b8c55)
Patrick Mezard <pmezard@gmail.com>
parents:
15005
diff
changeset
|
242 user, password = self.pwmgr.find_stored_password(url) |
0593e8f81c71
http: pass user to readauthforuri() (fix 4a43e23b8c55)
Patrick Mezard <pmezard@gmail.com>
parents:
15005
diff
changeset
|
243 res = readauthforuri(self.ui, url, user) |
14244
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
244 if res: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
245 group, auth = res |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
246 self.auth = auth |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
247 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
|
248 else: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
249 self.auth = None |
14346
bf85c2639700
httpconnection: correctly handle redirects from http to https
Augie Fackler <durin42@gmail.com>
parents:
14294
diff
changeset
|
250 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
|
251 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
252 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
|
253 keyfile = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
254 certfile = None |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
255 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
256 if args: # key_file |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
257 keyfile = args.pop(0) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
258 if args: # cert_file |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
259 certfile = args.pop(0) |
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 # 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
|
262 # hgrc, we prefer these |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
263 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
|
264 keyfile = self.auth['key'] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
265 certfile = self.auth['cert'] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
266 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
267 # let host port take precedence |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
268 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
|
269 host, port = host.rsplit(':', 1) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
270 port = int(port) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
271 if '[' in host: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
272 host = host[1:-1] |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
273 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
274 if keyfile: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
275 kwargs['keyfile'] = keyfile |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
276 if certfile: |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
277 kwargs['certfile'] = certfile |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
278 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
279 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
|
280 |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
281 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
|
282 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
|
283 **kwargs) |
e7525a555a64
url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
284 return con |