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
29
30
class PyCurlTransport(HttpTransportBase):
31
"""http client transport using pycurl
33
PyCurl is a Python binding to the C "curl" multiprotocol client.
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.
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)
44
def has(self, relpath):
45
self.curl = pycurl.Curl()
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')
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)
61
code = self.curl.getinfo(pycurl.HTTP_CODE)
62
if code == 404: # not found
64
elif code in (200, 302): # "ok", "found"
67
raise TransportError('http error %d probing for %s' %
68
(code, self.curl.getinfo(pycurl.EFFECTIVE_URL)))
35
72
def get(self, relpath):
36
return self._get_url(self.abspath(relpath))
38
def _get_url(self, abspath):
73
self.curl = pycurl.Curl()
74
abspath = self.abspath(relpath)
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',
51
self.curl.setopt(pycurl.HTTPHEADER, headers)
86
self.curl.setopt(pycurl.NOBODY, 0)
53
90
code = self.curl.getinfo(pycurl.HTTP_CODE)
55
92
raise NoSuchFile(abspath)
57
94
raise TransportError('http error %d acccessing %s' %
58
95
(code, self.curl.getinfo(pycurl.EFFECTIVE_URL)))
100
def _set_curl_cache_headers(self):
101
headers = ['Cache-control: must-revalidate',
103
self.curl.setopt(pycurl.HTTPHEADER, headers)
105
def _curl_perform(self):
106
"""Perform curl operation and translate exceptions."""
109
except pycurl.error, e:
110
# XXX: There seem to be no symbolic constants for these values.
112
# couldn't resolve host
113
raise NoSuchFile(self.curl.getinfo(pycurl.EFFECTIVE_URL), e)