~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Martin Pool
  • Date: 2006-01-13 09:57:13 UTC
  • mto: This revision was merged to the branch mainline in revision 1611.
  • Revision ID: mbp@sourcefrog.net-20060113095713-1fa5912229a3898e
Review updates of pycurl transport

Split them out into 

  bzrlib.transport.http             common base
  bzrlib.transport.http._urllib     pure python
  bzrlib.transport.http._pycurl     calls pycurl

Update to work with robert's nice transport test multiplexer.

Add PyCurlTransport.has() which does just a HEAD request; should be faster.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
import pycurl
23
23
 
24
24
from bzrlib.trace import mutter
25
 
from bzrlib.errors import TransportError, NoSuchFile
 
25
from bzrlib.errors import (TransportNotPossible, NoSuchFile, 
 
26
                           TransportError, ConnectionError)
26
27
from bzrlib.transport import Transport
27
28
from bzrlib.transport.http import HttpTransportBase
28
29
 
29
30
class PyCurlTransport(HttpTransportBase):
 
31
    """http client transport using pycurl
 
32
 
 
33
    PyCurl is a Python binding to the C "curl" multiprotocol client.
 
34
 
 
35
    This transport can be significantly faster than the builtin Python client. 
 
36
    Advantages include: DNS caching, connection keepalive, and ability to 
 
37
    set headers to allow caching.
 
38
    """
 
39
 
30
40
    def __init__(self, base):
31
41
        super(PyCurlTransport, self).__init__(base)
32
 
        self.curl = pycurl.Curl()
33
42
        mutter('imported pycurl %s' % pycurl.version)
34
43
 
 
44
    def has(self, relpath):
 
45
        self.curl = pycurl.Curl()
 
46
 
 
47
        abspath = self.abspath(relpath)
 
48
        if isinstance(abspath, unicode):
 
49
            # probably should raise an error instead; transport paths should
 
50
            # always simply be ascii.
 
51
            abspath = abspath.encode('ascii')
 
52
 
 
53
        self.curl.setopt(pycurl.URL, abspath)
 
54
        self._set_curl_cache_headers()
 
55
        # don't want the body - ie just do a HEAD request
 
56
        self.curl.setopt(pycurl.NOBODY, 1)
 
57
 
 
58
        self._curl_perform()
 
59
 
 
60
        try:
 
61
            code = self.curl.getinfo(pycurl.HTTP_CODE)
 
62
            if code == 404: # not found
 
63
                return False
 
64
            elif code in (200, 302): # "ok", "found"
 
65
                return True
 
66
            else:
 
67
                raise TransportError('http error %d probing for %s' %
 
68
                        (code, self.curl.getinfo(pycurl.EFFECTIVE_URL)))
 
69
        finally:
 
70
            del self.curl
 
71
        
35
72
    def get(self, relpath):
36
 
        return self._get_url(self.abspath(relpath))
37
 
 
38
 
    def _get_url(self, abspath):
 
73
        self.curl = pycurl.Curl()
 
74
        abspath = self.abspath(relpath)
39
75
        sio = StringIO()
40
76
        # pycurl needs plain ascii
41
77
        if isinstance(abspath, unicode):
45
81
            abspath = abspath.encode('ascii')
46
82
        self.curl.setopt(pycurl.URL, abspath)
47
83
        ## self.curl.setopt(pycurl.VERBOSE, 1)
 
84
        self._set_curl_cache_headers()
48
85
        self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
49
 
        headers = ['Cache-control: must-revalidate',
50
 
                   'Pragma:']
51
 
        self.curl.setopt(pycurl.HTTPHEADER, headers)
52
 
        self.curl.perform()
 
86
        self.curl.setopt(pycurl.NOBODY, 0)
 
87
 
 
88
        self._curl_perform()
 
89
 
53
90
        code = self.curl.getinfo(pycurl.HTTP_CODE)
54
91
        if code == 404:
55
92
            raise NoSuchFile(abspath)
57
94
            raise TransportError('http error %d acccessing %s' % 
58
95
                    (code, self.curl.getinfo(pycurl.EFFECTIVE_URL)))
59
96
        sio.seek(0)
 
97
        del self.curl
60
98
        return sio
61
99
 
 
100
    def _set_curl_cache_headers(self):
 
101
        headers = ['Cache-control: must-revalidate',
 
102
                   'Pragma:']
 
103
        self.curl.setopt(pycurl.HTTPHEADER, headers)
 
104
 
 
105
    def _curl_perform(self):
 
106
        """Perform curl operation and translate exceptions."""
 
107
        try:
 
108
            self.curl.perform()
 
109
        except pycurl.error, e:
 
110
            # XXX: There seem to be no symbolic constants for these values.
 
111
            if e[0] == 6:
 
112
                # couldn't resolve host
 
113
                raise NoSuchFile(self.curl.getinfo(pycurl.EFFECTIVE_URL), e)
 
114
 
62
115