/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/transport/http/__init__.py

  • Committer: Jelmer Vernooij
  • Date: 2020-02-07 02:14:30 UTC
  • mto: This revision was merged to the branch mainline in revision 7492.
  • Revision ID: jelmer@jelmer.uk-20200207021430-m49iq3x4x8xlib6x
Drop python2 support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
import urllib
36
36
import weakref
37
37
 
38
 
try:
39
 
    import http.client as http_client
40
 
except ImportError:
41
 
    import httplib as http_client
42
 
try:
43
 
    import urllib.request as urllib_request
44
 
except ImportError:  # python < 3
45
 
    import urllib2 as urllib_request
46
 
try:
47
 
    from urllib.parse import urljoin, splitport, splittype, splithost, urlencode
48
 
except ImportError:
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
51
41
 
52
42
# TODO: handle_response should be integrated into the http/__init__.py
53
43
from .response import handle_response
73
63
    urlutils,
74
64
)
75
65
from ...bzr.smart import medium
76
 
from ...sixish import (
77
 
    PY3,
78
 
    reraise,
79
 
    text_type,
80
 
)
81
66
from ...trace import mutter
82
67
from ...transport import (
83
68
    ConnectedTransport,
89
74
    return 'Breezy/%s' % breezy_version
90
75
 
91
76
 
92
 
try:
93
 
    _ = (ssl.match_hostname, ssl.CertificateError)
94
 
except AttributeError:
95
 
    # Provide fallbacks for python < 2.7.9
96
 
    def match_hostname(cert, host):
97
 
        trace.warning(
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
102
 
 
103
 
 
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 = [
186
159
kerberos = None
187
160
 
188
161
 
189
 
class addinfourl(urllib_request.addinfourl):
190
 
    '''Replacement addinfourl class compatible with python-2.7's xmlrpclib
191
 
 
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.
196
 
    '''
197
 
 
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)
202
 
 
203
 
    def getheaders(self):
204
 
        if self.headers is None:
205
 
            raise http_client.ResponseNotReady()
206
 
        return list(self.headers.items())
207
 
 
208
 
 
209
162
class _ReportingFileSocket(object):
210
163
 
211
164
    def __init__(self, filesock, report_activity=None):
284
237
    # 8k chunks should be fine.
285
238
    _discarded_buf_size = 8192
286
239
 
287
 
    if PY3:
288
 
        def __init__(self, sock, debuglevel=0, method=None, url=None):
289
 
            self.url = url
290
 
            super(Response, self).__init__(
291
 
                sock, debuglevel=debuglevel, method=method, url=url)
 
240
    def __init__(self, sock, debuglevel=0, method=None, url=None):
 
241
        self.url = url
 
242
        super(Response, self).__init__(
 
243
            sock, debuglevel=debuglevel, method=method, url=url)
292
244
 
293
245
    def begin(self):
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)
427
 
        if PY3:
428
 
            http_client.HTTPConnection.__init__(self, host, port)
429
 
        else:
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
434
382
 
445
393
                 proxied_host=None,
446
394
                 report_activity=None, ca_certs=None):
447
395
        AbstractHTTPConnection.__init__(self, report_activity=report_activity)
448
 
        if PY3:
449
 
            http_client.HTTPSConnection.__init__(
450
 
                self, host, port, key_file, cert_file)
451
 
        else:
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
457
400
 
547
490
 
548
491
    def set_proxy(self, proxy, type):
549
492
        """Set the proxy and remember the proxied host."""
550
 
        if PY3:
551
 
            host, port = splitport(self.host)
552
 
        else:
553
 
            host, port = splitport(self.get_host())
 
493
        host, port = splitport(self.host)
554
494
        if port is None:
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
725
 
            if PY3:
726
 
                origin_req_host = request.origin_req_host
727
 
            else:
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)
 
672
            raise exc_val
736
673
        else:
737
674
            if first_try:
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
773
710
                    # do.
774
 
                    if PY3:
775
 
                        selector = request.selector
776
 
                    else:
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(),
780
714
                                                      selector),
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)
790
724
        return response
791
725
 
792
726
    def do_open(self, http_class, request, first_try=True):
813
747
 
814
748
        try:
815
749
            method = request.get_method()
816
 
            if PY3:
817
 
                url = request.selector
818
 
            else:
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
855
786
 
856
 
        if PY3:
857
 
            response.msg = response.reason
858
 
            return response
859
 
 
860
 
# FIXME: HTTPConnection does not fully support 100-continue (the
861
 
# server responses are just ignored)
862
 
 
863
 
#        if code == 100:
864
 
#            mutter('Will send the body')
865
 
#            # We can send the body now
866
 
#            body = request.data
867
 
#            if body is None:
868
 
#                raise URLError("No data given")
869
 
#            connection.send(body)
870
 
#            response = connection.getresponse()
871
 
 
872
 
        if self._debuglevel >= 2:
873
 
            print('Receives response: %r' % response)
874
 
            print('  For: %r(%r)' % (request.get_method(),
875
 
                                     request.get_full_url()))
876
 
 
877
 
        if convert_to_addinfourl:
878
 
            # Shamelessly copied from urllib_request
879
 
            req = request
880
 
            r = response
881
 
            r.recv = r.read
882
 
            fp = socket._fileobject(r, bufsize=65536)
883
 
            resp = addinfourl(fp, r.msg, req.get_full_url())
884
 
            resp.code = r.status
885
 
            resp.msg = r.reason
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'
893
 
                try:
894
 
                    version = version % (resp.version / 10,
895
 
                                         resp.version % 10)
896
 
                except:
897
 
                    version = 'HTTP/%r' % resp.version
898
 
                trace.mutter('< %s %s %s' % (version, resp.code,
899
 
                                             resp.msg))
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')
904
 
        else:
905
 
            resp = response
906
 
        return resp
 
787
        response.msg = response.reason
 
788
        return response
907
789
 
908
790
 
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.
999
881
 
1000
 
        if PY3:
1001
 
            origin_req_host = req.origin_req_host
1002
 
        else:
1003
 
            origin_req_host = req.get_origin_req_host()
 
882
        origin_req_host = req.origin_req_host
1004
883
 
1005
884
        if code in (301, 302, 303, 307):
1006
885
            return Request(req.get_method(), newurl,
1185
1064
        return None
1186
1065
 
1187
1066
    def set_proxy(self, request, type):
1188
 
        if PY3:
1189
 
            host = request.host
1190
 
        else:
1191
 
            host = request.get_host()
 
1067
        host = request.host
1192
1068
        if self.proxy_bypass(host):
1193
1069
            return request
1194
1070
 
1323
1199
                # Let's be ready for next round
1324
1200
                self._retry_count = None
1325
1201
                return None
1326
 
        if PY3:
1327
 
            server_headers = headers.get_all(self.auth_required_header)
1328
 
        else:
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.
1684
1557
        return True
1685
1558
 
1686
1559
    def build_auth_header(self, auth, request):
1687
 
        if PY3:
1688
 
            selector = request.selector
1689
 
        else:
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)
1693
1563
 
2005
1875
            def getheader(self, name, default=None):
2006
1876
                if self._actual.headers is None:
2007
1877
                    raise http_client.ResponseNotReady()
2008
 
                if PY3:
2009
 
                    return self._actual.headers.get(name, default)
2010
 
                else:
2011
 
                    return self._actual.headers.getheader(name, default)
 
1878
                return self._actual.headers.get(name, default)
2012
1879
 
2013
1880
            def getheaders(self):
2014
1881
                if self._actual.headers is None: