~toddy/bzr/bzr.i18n

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/_pycurl.py

  • Committer: Tobias Toedter
  • Date: 2007-12-30 18:52:13 UTC
  • mfrom: (2438.1.708 +trunk)
  • Revision ID: t.toedter@gmx.net-20071230185213-7xiqpbtshmnsf073
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 
34
34
import os
35
35
from cStringIO import StringIO
 
36
import httplib
36
37
import sys
37
38
 
38
39
from bzrlib import (
45
46
from bzrlib.trace import mutter
46
47
from bzrlib.transport.http import (
47
48
    ca_bundle,
48
 
    _extract_headers,
49
49
    HttpTransportBase,
50
50
    response,
51
51
    )
123
123
            # connect to the http server until the first request (which had
124
124
            # just called us).
125
125
            connection = pycurl.Curl()
126
 
            self._set_connection(connection, None)
 
126
            # First request, initialize credentials.
 
127
            auth = self._create_auth()
 
128
            # Proxy handling is out of reach, so we punt
 
129
            self._set_connection(connection, auth)
127
130
        return connection
128
131
 
129
132
    def has(self, relpath):
208
211
 
209
212
        return code, data
210
213
 
 
214
    # The parent class use 0 to minimize the requests, but since we can't
 
215
    # exploit the results as soon as they are received (pycurl limitation) we'd
 
216
    # better issue more requests and provide a more responsive UI do the cost
 
217
    # of more latency costs.
 
218
    # If you modify this, think about modifying the comment in http/__init__.py
 
219
    # too.
 
220
    _get_max_size = 4 * 1024 * 1024
 
221
 
211
222
    def _get_ranged(self, relpath, offsets, tail_amount):
212
223
        """Make a request for just part of the file."""
213
224
        curl = self._get_curl()
222
233
        data.seek(0)
223
234
 
224
235
        code = curl.getinfo(pycurl.HTTP_CODE)
225
 
        # mutter('header:\n%r', header.getvalue())
226
 
        headers = _extract_headers(header.getvalue(), abspath)
227
 
        # handle_response will raise NoSuchFile, etc based on the response code
228
 
        return code, response.handle_response(abspath, code, headers, data)
 
236
 
 
237
        if code == 404: # not found
 
238
            raise errors.NoSuchFile(abspath)
 
239
        elif code in (400, 416):
 
240
            # We don't know which, but one of the ranges we specified was
 
241
            # wrong.
 
242
            raise errors.InvalidHttpRange(abspath, range_header,
 
243
                                          'Server return code %d'
 
244
                                          % curl.getinfo(pycurl.HTTP_CODE))
 
245
        msg = self._parse_headers(header)
 
246
        return code, response.handle_response(abspath, code, msg, data)
 
247
 
 
248
    def _parse_headers(self, status_and_headers):
 
249
        """Transform the headers provided by curl into an HTTPMessage"""
 
250
        status_and_headers.seek(0)
 
251
        # Ignore status line
 
252
        status_and_headers.readline()
 
253
        msg = httplib.HTTPMessage(status_and_headers)
 
254
        return msg
229
255
 
230
256
    def _post(self, body_bytes):
231
257
        fake_file = StringIO(body_bytes)
242
268
        self._curl_perform(curl, header, ['Expect: '])
243
269
        data.seek(0)
244
270
        code = curl.getinfo(pycurl.HTTP_CODE)
245
 
        headers = _extract_headers(header.getvalue(), abspath)
246
 
        return code, response.handle_response(abspath, code, headers, data)
 
271
        msg = self._parse_headers(header)
 
272
        return code, response.handle_response(abspath, code, msg, data)
247
273
 
248
274
    def _raise_curl_http_error(self, curl, info=None):
249
275
        code = curl.getinfo(pycurl.HTTP_CODE)
272
298
        curl.setopt(pycurl.USERAGENT, ua_str)
273
299
        if self.cabundle:
274
300
            curl.setopt(pycurl.CAINFO, self.cabundle)
 
301
        # Set accepted auth methods
 
302
        curl.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_ANY)
 
303
        curl.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY)
 
304
        auth = self._get_credentials()
 
305
        user = auth.get('user', None)
 
306
        password = auth.get('password', None)
 
307
        userpass = None
 
308
        if user is not None:
 
309
            userpass = user + ':'
 
310
            if password is not None: # '' is a valid password
 
311
                userpass += password
 
312
            curl.setopt(pycurl.USERPWD, userpass)
275
313
 
276
314
    def _curl_perform(self, curl, header, more_headers=[]):
277
315
        """Perform curl operation and translate exceptions."""
297
335
                raise errors.ConnectionError(
298
336
                    'curl connection error (%s)\non %s' % (e[1], url))
299
337
            elif e[0] == CURLE_PARTIAL_FILE:
300
 
                # Pycurl itself has detected a short read.  We do
301
 
                # not have all the information for the
302
 
                # ShortReadvError, but that should be enough
 
338
                # Pycurl itself has detected a short read.  We do not have all
 
339
                # the information for the ShortReadvError, but that should be
 
340
                # enough
303
341
                raise errors.ShortReadvError(url,
304
342
                                             offset='unknown', length='unknown',
305
343
                                             actual='unknown',
306
344
                                             extra='Server aborted the request')
307
 
            # jam 20060713 The code didn't use to re-raise the exception here,
308
 
            # but that seemed bogus
309
345
            raise
310
346
        code = curl.getinfo(pycurl.HTTP_CODE)
311
347
        if code in (301, 302, 303, 307):
312
348
            url = curl.getinfo(pycurl.EFFECTIVE_URL)
313
 
            headers = _extract_headers(header.getvalue(), url)
314
 
            redirected_to = headers['Location']
 
349
            msg = self._parse_headers(header)
 
350
            redirected_to = msg.getheader('location')
315
351
            raise errors.RedirectRequested(url,
316
352
                                           redirected_to,
317
353
                                           is_permanent=(code == 301),