/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/_urllib.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2018-05-05 16:58:40 UTC
  • mfrom: (6929.11.2 urllib3)
  • Revision ID: breezy.the.bot@gmail.com-20180505165840-3a69fitc2f4n7vf9
Integrate the urllib-specific bits into the main HttpTransport.

Merged from https://code.launchpad.net/~jelmer/brz/urllib-integration/+merge/342487

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
from __future__ import absolute_import
18
 
 
19
 
from ... import (
20
 
    errors,
21
 
    trace,
22
 
    )
23
 
from .. import http
24
 
# TODO: handle_response should be integrated into the http/__init__.py
25
 
from .response import handle_response
26
 
from ._urllib2_wrappers import (
27
 
    Opener,
28
 
    Request,
29
 
    )
30
 
 
31
 
 
32
 
class HttpTransport_urllib(http.HttpTransportBase):
33
 
    """Python urllib transport for http and https."""
34
 
 
35
 
    # In order to debug we have to issue our traces in sync with
36
 
    # httplib, which use print :(
37
 
    _debuglevel = 0
38
 
 
39
 
    _opener_class = Opener
40
 
 
41
 
    def __init__(self, base, _from_transport=None, ca_certs=None):
42
 
        super(HttpTransport_urllib, self).__init__(
43
 
            base, 'urllib', _from_transport=_from_transport)
44
 
        if _from_transport is not None:
45
 
            self._opener = _from_transport._opener
46
 
        else:
47
 
            self._opener = self._opener_class(
48
 
                report_activity=self._report_activity, ca_certs=ca_certs)
49
 
 
50
 
    def _perform(self, request):
51
 
        """Send the request to the server and handles common errors.
52
 
 
53
 
        :returns: urllib2 Response object
54
 
        """
55
 
        connection = self._get_connection()
56
 
        if connection is not None:
57
 
            # Give back shared info
58
 
            request.connection = connection
59
 
            (auth, proxy_auth) = self._get_credentials()
60
 
            # Clean the httplib.HTTPConnection pipeline in case the previous
61
 
            # request couldn't do it
62
 
            connection.cleanup_pipe()
63
 
        else:
64
 
            # First request, initialize credentials.
65
 
            # scheme and realm will be set by the _urllib2_wrappers.AuthHandler
66
 
            auth = self._create_auth()
67
 
            # Proxy initialization will be done by the first proxied request
68
 
            proxy_auth = dict()
69
 
        # Ensure authentication info is provided
70
 
        request.auth = auth
71
 
        request.proxy_auth = proxy_auth
72
 
 
73
 
        if self._debuglevel > 0:
74
 
            print('perform: %s base: %s, url: %s' % (request.method, self.base,
75
 
                                                     request.get_full_url()))
76
 
        response = self._opener.open(request)
77
 
        if self._get_connection() is not request.connection:
78
 
            # First connection or reconnection
79
 
            self._set_connection(request.connection,
80
 
                                 (request.auth, request.proxy_auth))
81
 
        else:
82
 
            # http may change the credentials while keeping the
83
 
            # connection opened
84
 
            self._update_credentials((request.auth, request.proxy_auth))
85
 
 
86
 
        code = response.code
87
 
        if (request.follow_redirections is False
88
 
            and code in (301, 302, 303, 307)):
89
 
            raise errors.RedirectRequested(request.get_full_url(),
90
 
                                           request.redirected_to,
91
 
                                           is_permanent=(code == 301))
92
 
 
93
 
        if request.redirected_to is not None:
94
 
            trace.mutter('redirected from: %s to: %s' % (request.get_full_url(),
95
 
                                                         request.redirected_to))
96
 
 
97
 
        return response
98
 
 
99
 
    def disconnect(self):
100
 
        connection = self._get_connection()
101
 
        if connection is not None:
102
 
            connection.close()
103
 
 
104
 
    def _get(self, relpath, offsets, tail_amount=0):
105
 
        """See HttpTransport._get"""
106
 
        abspath = self._remote_path(relpath)
107
 
        headers = {}
108
 
        accepted_errors = [200, 404]
109
 
        if offsets or tail_amount:
110
 
            range_header = self._attempted_range_header(offsets, tail_amount)
111
 
            if range_header is not None:
112
 
                accepted_errors.append(206)
113
 
                accepted_errors.append(400)
114
 
                accepted_errors.append(416)
115
 
                bytes = 'bytes=' + range_header
116
 
                headers = {'Range': bytes}
117
 
 
118
 
        request = Request('GET', abspath, None, headers,
119
 
                          accepted_errors=accepted_errors)
120
 
        response = self._perform(request)
121
 
 
122
 
        code = response.code
123
 
        if code == 404: # not found
124
 
            raise errors.NoSuchFile(abspath)
125
 
        elif code in (400, 416):
126
 
            # We don't know which, but one of the ranges we specified was
127
 
            # wrong.
128
 
            raise errors.InvalidHttpRange(abspath, range_header,
129
 
                                          'Server return code %d' % code)
130
 
 
131
 
        data = handle_response(abspath, code, response.info(), response)
132
 
        return code, data
133
 
 
134
 
    def _post(self, body_bytes):
135
 
        abspath = self._remote_path('.bzr/smart')
136
 
        # We include 403 in accepted_errors so that send_http_smart_request can
137
 
        # handle a 403.  Otherwise a 403 causes an unhandled TransportError.
138
 
        response = self._perform(
139
 
            Request('POST', abspath, body_bytes,
140
 
                    {'Content-Type': 'application/octet-stream'},
141
 
                    accepted_errors=[200, 403]))
142
 
        code = response.code
143
 
        data = handle_response(abspath, code, response.info(), response)
144
 
        return code, data
145
 
 
146
 
    def _head(self, relpath):
147
 
        """Request the HEAD of a file.
148
 
 
149
 
        Performs the request and leaves callers handle the results.
150
 
        """
151
 
        abspath = self._remote_path(relpath)
152
 
        request = Request('HEAD', abspath,
153
 
                          accepted_errors=[200, 404])
154
 
        response = self._perform(request)
155
 
 
156
 
        return response
157
 
 
158
 
    def has(self, relpath):
159
 
        """Does the target location exist?
160
 
        """
161
 
        response = self._head(relpath)
162
 
 
163
 
        code = response.code
164
 
        if code == 200: # "ok",
165
 
            return True
166
 
        else:
167
 
            return False
168
 
 
169
 
 
170
 
def get_test_permutations():
171
 
    """Return the permutations to be used in testing."""
172
 
    from breezy.tests import (
173
 
        features,
174
 
        http_server,
175
 
        )
176
 
    permutations = [(HttpTransport_urllib, http_server.HttpServer_urllib),]
177
 
    if features.HTTPSServerFeature.available():
178
 
        from breezy.tests import (
179
 
            https_server,
180
 
            ssl_certs,
181
 
            )
182
 
 
183
 
        class HTTPS_urllib_transport(HttpTransport_urllib):
184
 
 
185
 
            def __init__(self, base, _from_transport=None):
186
 
                super(HTTPS_urllib_transport, self).__init__(
187
 
                    base, _from_transport=_from_transport,
188
 
                    ca_certs=ssl_certs.build_path('ca.crt'))
189
 
 
190
 
        permutations.append((HTTPS_urllib_transport,
191
 
                             https_server.HTTPSServer_urllib))
192
 
    return permutations