39
import http.client as http_client
41
import httplib as http_client
43
import urllib.request as urllib_request
44
except ImportError: # python < 3
45
import urllib2 as urllib_request
47
from urllib.parse import urljoin, splitport, splittype, splithost, urlencode
49
from urlparse import urljoin
50
from urllib import splitport, splittype, splithost, urlencode
38
import http.client as http_client
39
import urllib.request as urllib_request
40
from urllib.parse import urljoin, splitport, splittype, splithost, urlencode
52
42
# TODO: handle_response should be integrated into the http/__init__.py
53
43
from .response import handle_response
89
74
return 'Breezy/%s' % breezy_version
93
_ = (ssl.match_hostname, ssl.CertificateError)
94
except AttributeError:
95
# Provide fallbacks for python < 2.7.9
96
def match_hostname(cert, host):
98
'%s cannot be verified, https certificates verification is only'
99
' available for python versions >= 2.7.9' % (host,))
100
ssl.match_hostname = match_hostname
101
ssl.CertificateError = ValueError
104
77
# Note for packagers: if there is no package providing certs for your platform,
105
78
# the curl project produces http://curl.haxx.se/ca/cacert.pem weekly.
106
79
_ssl_ca_certs_known_locations = [
189
class addinfourl(urllib_request.addinfourl):
190
'''Replacement addinfourl class compatible with python-2.7's xmlrpclib
192
In python-2.7, xmlrpclib expects that the response object that it receives
193
has a getheader method. http_client.HTTPResponse provides this but
194
urllib_request.addinfourl does not. Add the necessary functions here, ported to
195
use the internal data structures of addinfourl.
198
def getheader(self, name, default=None):
199
if self.headers is None:
200
raise http_client.ResponseNotReady()
201
return self.headers.getheader(name, default)
203
def getheaders(self):
204
if self.headers is None:
205
raise http_client.ResponseNotReady()
206
return list(self.headers.items())
209
162
class _ReportingFileSocket(object):
211
164
def __init__(self, filesock, report_activity=None):
284
237
# 8k chunks should be fine.
285
238
_discarded_buf_size = 8192
288
def __init__(self, sock, debuglevel=0, method=None, url=None):
290
super(Response, self).__init__(
291
sock, debuglevel=debuglevel, method=method, url=url)
240
def __init__(self, sock, debuglevel=0, method=None, url=None):
242
super(Response, self).__init__(
243
sock, debuglevel=debuglevel, method=method, url=url)
294
246
"""Begin to read the response from the server.
424
376
def __init__(self, host, port=None, proxied_host=None,
425
377
report_activity=None, ca_certs=None):
426
378
AbstractHTTPConnection.__init__(self, report_activity=report_activity)
428
http_client.HTTPConnection.__init__(self, host, port)
430
# Use strict=True since we don't support HTTP/0.9
431
http_client.HTTPConnection.__init__(self, host, port, strict=True)
379
http_client.HTTPConnection.__init__(self, host, port)
432
380
self.proxied_host = proxied_host
433
381
# ca_certs is ignored, it's only relevant for https
445
393
proxied_host=None,
446
394
report_activity=None, ca_certs=None):
447
395
AbstractHTTPConnection.__init__(self, report_activity=report_activity)
449
http_client.HTTPSConnection.__init__(
450
self, host, port, key_file, cert_file)
452
# Use strict=True since we don't support HTTP/0.9
453
http_client.HTTPSConnection.__init__(self, host, port,
454
key_file, cert_file, strict=True)
396
http_client.HTTPSConnection.__init__(
397
self, host, port, key_file, cert_file)
455
398
self.proxied_host = proxied_host
456
399
self.ca_certs = ca_certs
548
491
def set_proxy(self, proxy, type):
549
492
"""Set the proxy and remember the proxied host."""
551
host, port = splitport(self.host)
553
host, port = splitport(self.get_host())
493
host, port = splitport(self.host)
555
495
# We need to set the default port ourselves way before it gets set
556
496
# in the HTTP[S]Connection object at build time.
722
662
exc_type, exc_val, exc_tb = sys.exc_info()
723
663
if exc_type == socket.gaierror:
724
664
# No need to retry, that will not help
726
origin_req_host = request.origin_req_host
728
origin_req_host = request.get_origin_req_host()
665
origin_req_host = request.origin_req_host
729
666
raise errors.ConnectionError("Couldn't resolve host '%s'"
730
667
% origin_req_host,
731
668
orig_error=exc_val)
732
669
elif isinstance(exc_val, http_client.ImproperConnectionState):
733
670
# The http_client pipeline is in incorrect state, it's a bug in our
734
671
# implementation.
735
reraise(exc_type, exc_val, exc_tb)
738
675
if self._debuglevel >= 2:
771
708
# far outside our scope, so closing the
772
709
# connection and retrying is the best we can
775
selector = request.selector
777
selector = request.get_selector()
711
selector = request.selector
778
712
my_exception = errors.ConnectionError(
779
713
msg='while sending %s %s:' % (request.get_method(),
786
720
url = request.get_full_url()
787
721
print(' Failed again, %s %r' % (method, url))
788
722
print(' Will raise: [%r]' % my_exception)
789
reraise(type(my_exception), my_exception, exc_tb)
723
raise my_exception.with_traceback(exc_tb)
792
726
def do_open(self, http_class, request, first_try=True):
815
749
method = request.get_method()
817
url = request.selector
819
url = request.get_selector()
750
url = request.selector
820
751
if sys.version_info[:2] >= (3, 6):
821
752
connection._send_request(method, url,
822
753
# FIXME: implements 100-continue
853
784
response = self.retry_or_raise(http_class, request, first_try)
854
785
convert_to_addinfourl = False
857
response.msg = response.reason
860
# FIXME: HTTPConnection does not fully support 100-continue (the
861
# server responses are just ignored)
864
# mutter('Will send the body')
865
# # We can send the body now
866
# body = request.data
868
# raise URLError("No data given")
869
# connection.send(body)
870
# response = connection.getresponse()
872
if self._debuglevel >= 2:
873
print('Receives response: %r' % response)
874
print(' For: %r(%r)' % (request.get_method(),
875
request.get_full_url()))
877
if convert_to_addinfourl:
878
# Shamelessly copied from urllib_request
882
fp = socket._fileobject(r, bufsize=65536)
883
resp = addinfourl(fp, r.msg, req.get_full_url())
886
resp.version = r.version
887
if self._debuglevel >= 2:
888
print('Create addinfourl: %r' % resp)
889
print(' For: %r(%r)' % (request.get_method(),
890
request.get_full_url()))
891
if 'http' in debug.debug_flags:
892
version = 'HTTP/%d.%d'
894
version = version % (resp.version / 10,
897
version = 'HTTP/%r' % resp.version
898
trace.mutter('< %s %s %s' % (version, resp.code,
900
# Use the raw header lines instead of treating resp.info() as a
901
# dict since we may miss duplicated headers otherwise.
902
hdrs = [h.rstrip('\r\n') for h in resp.info().headers]
903
trace.mutter('< ' + '\n< '.join(hdrs) + '\n')
787
response.msg = response.reason
909
791
class HTTPHandler(AbstractHTTPHandler):
997
879
# and that we MAY avoid following the redirections. But
998
880
# if we want to be sure, we MUST follow them.
1001
origin_req_host = req.origin_req_host
1003
origin_req_host = req.get_origin_req_host()
882
origin_req_host = req.origin_req_host
1005
884
if code in (301, 302, 303, 307):
1006
885
return Request(req.get_method(), newurl,
1323
1199
# Let's be ready for next round
1324
1200
self._retry_count = None
1327
server_headers = headers.get_all(self.auth_required_header)
1329
server_headers = headers.getheaders(self.auth_required_header)
1202
server_headers = headers.get_all(self.auth_required_header)
1330
1203
if not server_headers:
1331
1204
# The http error MUST have the associated
1332
1205
# header. This must never happen in production code.
1686
1559
def build_auth_header(self, auth, request):
1688
selector = request.selector
1690
selector = request.get_selector()
1560
selector = request.selector
1691
1561
url_scheme, url_selector = splittype(selector)
1692
1562
sel_host, uri = splithost(url_selector)
2005
1875
def getheader(self, name, default=None):
2006
1876
if self._actual.headers is None:
2007
1877
raise http_client.ResponseNotReady()
2009
return self._actual.headers.get(name, default)
2011
return self._actual.headers.getheader(name, default)
1878
return self._actual.headers.get(name, default)
2013
1880
def getheaders(self):
2014
1881
if self._actual.headers is None: