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

  • Committer: Robert Collins
  • Date: 2007-08-07 22:59:45 UTC
  • mfrom: (2681 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2682.
  • Revision ID: robertc@robertcollins.net-20070807225945-dlxppeb3we4lh897
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
import urllib
19
19
import urlparse
20
20
 
21
 
from bzrlib import errors
 
21
from bzrlib import (
 
22
    errors,
 
23
    urlutils,
 
24
    )
22
25
from bzrlib.trace import mutter
23
26
from bzrlib.transport import register_urlparse_netloc_protocol
24
27
from bzrlib.transport.http import HttpTransportBase
44
47
 
45
48
    _opener_class = Opener
46
49
 
47
 
    def __init__(self, base, from_transport=None):
48
 
        """Set the base path where files will be stored."""
49
 
        if from_transport is not None:
50
 
            super(HttpTransport_urllib, self).__init__(base, from_transport)
51
 
            self._connection = from_transport._connection
52
 
            self._auth = from_transport._auth
53
 
            self._proxy_auth = from_transport._proxy_auth
54
 
 
55
 
            self._opener = from_transport._opener
 
50
    def __init__(self, base, _from_transport=None):
 
51
        super(HttpTransport_urllib, self).__init__(
 
52
            base, _from_transport=_from_transport)
 
53
        if _from_transport is not None:
 
54
            self._opener = _from_transport._opener
56
55
        else:
57
 
            # urllib2 will be confused if it find authentication
58
 
            # info in the urls. So we handle them separatly.
59
 
            # Note: we don't need to when cloning because it was
60
 
            # already done.
61
 
            clean_base, user, password = extract_credentials(base)
62
 
            super(HttpTransport_urllib, self).__init__(clean_base,
63
 
                                                       from_transport)
64
 
            self._connection = None
65
56
            self._opener = self._opener_class()
66
57
 
67
 
            authuri = extract_authentication_uri(self._real_abspath(self._path))
68
 
            self._auth = {'user': user, 'password': password,
69
 
                          'authuri': authuri}
 
58
    def _remote_path(self, relpath):
 
59
        """Produce absolute path, adjusting protocol."""
 
60
        relative = urlutils.unescape(relpath).encode('utf-8')
 
61
        path = self._combine_paths(self._path, relative)
 
62
        # urllib2 will be confused if it find authentication
 
63
        # info (user, password) in the urls. So we handle them separatly.
 
64
        return self._unsplit_url(self._unqualified_scheme,
 
65
                                 None, None, self._host, self._port, path)
 
66
 
 
67
    def _perform(self, request):
 
68
        """Send the request to the server and handles common errors.
 
69
 
 
70
        :returns: urllib2 Response object
 
71
        """
 
72
        connection = self._get_connection()
 
73
        if connection is not None:
 
74
            # Give back shared info
 
75
            request.connection = connection
 
76
            (auth, proxy_auth) = self._get_credentials()
 
77
        else:
 
78
            # First request, intialize credentials
 
79
            user = self._user
 
80
            password = self._password
 
81
            authuri = self._remote_path('.')
 
82
            auth = {'user': user, 'password': password, 'authuri': authuri}
 
83
 
70
84
            if user and password is not None: # '' is a valid password
71
85
                # Make the (user, password) available to urllib2
72
86
                # We default to a realm of None to catch them all.
73
87
                self._opener.password_manager.add_password(None, authuri,
74
88
                                                           user, password)
75
 
            self._proxy_auth = {}
76
 
 
77
 
    def _perform(self, request):
78
 
        """Send the request to the server and handles common errors.
79
 
 
80
 
        :returns: urllib2 Response object
81
 
        """
82
 
        if self._connection is not None:
83
 
            # Give back shared info
84
 
            request.connection = self._connection
 
89
            proxy_auth = {}
85
90
        # Ensure authentication info is provided
86
 
        request.auth = self._auth
87
 
        request.proxy_auth = self._proxy_auth
 
91
        request.auth = auth
 
92
        request.proxy_auth = proxy_auth
88
93
 
89
94
        mutter('%s: [%s]' % (request.method, request.get_full_url()))
90
95
        if self._debuglevel > 0:
91
96
            print 'perform: %s base: %s, url: %s' % (request.method, self.base,
92
97
                                                     request.get_full_url())
93
98
        response = self._opener.open(request)
94
 
        if self._connection is None:
95
 
            # Acquire connection when the first request is able
96
 
            # to connect to the server
97
 
            self._connection = request.connection
98
 
        # Always get auth parameters, they may change
99
 
        self._auth = request.auth
100
 
        self._proxy_auth = request.proxy_auth
 
99
        if self._get_connection() is not request.connection:
 
100
            # First connection or reconnection
 
101
            self._set_connection(request.connection,
 
102
                                 (request.auth, request.proxy_auth))
 
103
        else:
 
104
            # http may change the credentials while keeping the
 
105
            # connection opened
 
106
            self._update_credentials((request.auth, request.proxy_auth))
101
107
 
102
108
        code = response.code
103
109
        if request.follow_redirections is False \
105
111
            raise errors.RedirectRequested(request.get_full_url(),
106
112
                                           request.redirected_to,
107
113
                                           is_permament=(code == 301),
108
 
                                           qual_proto=self._qualified_proto)
 
114
                                           qual_proto=self._scheme)
109
115
 
110
116
        if request.redirected_to is not None:
111
117
            mutter('redirected from: %s to: %s' % (request.get_full_url(),
116
122
    def _get(self, relpath, offsets, tail_amount=0):
117
123
        """See HttpTransport._get"""
118
124
 
119
 
        abspath = self._real_abspath(relpath)
 
125
        abspath = self._remote_path(relpath)
120
126
        headers = {}
121
127
        accepted_errors = [200, 404]
122
128
        if offsets or tail_amount:
133
139
 
134
140
        code = response.code
135
141
        if code == 404: # not found
136
 
            self._connection.fake_close()
 
142
            self._get_connection().fake_close()
137
143
            raise errors.NoSuchFile(abspath)
138
144
 
139
145
        data = handle_response(abspath, code, response.headers, response)
140
146
        # Close response to free the httplib.HTTPConnection pipeline
141
 
        self._connection.fake_close()
 
147
        self._get_connection().fake_close()
142
148
        return code, data
143
149
 
144
150
    def _post(self, body_bytes):
145
 
        abspath = self._real_abspath('.bzr/smart')
 
151
        abspath = self._remote_path('.bzr/smart')
146
152
        response = self._perform(Request('POST', abspath, body_bytes))
147
153
        code = response.code
148
154
        data = handle_response(abspath, code, response.headers, response)
149
155
        # Close response to free the httplib.HTTPConnection pipeline
150
 
        self._connection.fake_close()
 
156
        self._get_connection().fake_close()
151
157
        return code, data
152
158
 
153
159
    def should_cache(self):
160
166
 
161
167
        Performs the request and leaves callers handle the results.
162
168
        """
163
 
        abspath = self._real_abspath(relpath)
 
169
        abspath = self._remote_path(relpath)
164
170
        request = Request('HEAD', abspath,
165
171
                          accepted_errors=[200, 404])
166
172
        response = self._perform(request)
167
173
 
168
 
        self._connection.fake_close()
 
174
        self._get_connection().fake_close()
169
175
        return response
170
176
 
171
177
    def has(self, relpath):