19
19
from bzrlib.transport import Transport, register_transport
20
20
from bzrlib.errors import (TransportNotPossible, NoSuchFile,
21
NonRelativePath, TransportError, ConnectionError)
21
TransportError, ConnectionError)
23
23
from cStringIO import StringIO
24
import urllib, urllib2
27
27
from bzrlib.errors import BzrError, BzrCheckError
29
29
from bzrlib.trace import mutter
32
def extract_auth(url, password_manager):
34
Extract auth parameters from am HTTP/HTTPS url and add them to the given
35
password manager. Return the url, minus those auth parameters (which
38
assert url.startswith('http://') or url.startswith('https://')
39
scheme, host = url.split('//', 1)
41
host, path = host.split('/', 1)
47
auth, host = host.split('@', 1)
49
username, password = auth.split(':', 1)
51
username, password = auth, None
53
host, port = host.split(':', 1)
55
# FIXME: if password isn't given, should we ask for it?
56
if password is not None:
57
username = urllib.unquote(username)
58
password = urllib.unquote(password)
59
password_manager.add_password(None, host, username, password)
60
url = scheme + '//' + host + port + path
34
mutter("get_url %s", url)
35
url_f = urllib2.urlopen(url)
65
mutter("get_url %s" % url)
66
manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
67
url = extract_auth(url, manager)
68
auth_handler = urllib2.HTTPBasicAuthHandler(manager)
69
opener = urllib2.build_opener(auth_handler)
70
url_f = opener.open(url)
38
class HttpTransportError(TransportError):
41
73
class HttpTransport(Transport):
42
74
"""This is the transport agent for http:// access.
119
151
cleaner if we just do an http HEAD request, and parse
123
f = get_url(self.abspath(relpath))
156
path = self.abspath(relpath)
124
158
# Without the read and then close()
125
159
# we tend to have busy sockets.
129
163
except urllib2.URLError, e:
164
mutter('url error code: %s for has url: %r', e.code, path)
130
165
if e.code == 404:
133
168
except IOError, e:
169
mutter('io error: %s %s for has url: %r',
170
e.errno, errno.errorcode.get(e.errno), path)
134
171
if e.errno == errno.ENOENT:
136
raise HttpTransportError(orig_error=e)
173
raise TransportError(orig_error=e)
138
175
def get(self, relpath, decode=False):
139
176
"""Get the file at the given relative path.
141
178
:param relpath: The relative path to the file
144
return get_url(self.abspath(relpath))
182
path = self.abspath(relpath)
145
184
except urllib2.HTTPError, e:
185
mutter('url error code: %s for has url: %r', e.code, path)
146
186
if e.code == 404:
147
raise NoSuchFile(msg = "Error retrieving %s: %s"
148
% (self.abspath(relpath), str(e)),
187
raise NoSuchFile(path, extra=e)
151
189
except (BzrError, IOError), e:
190
if hasattr(e, 'errno'):
191
mutter('io error: %s %s for has url: %r',
192
e.errno, errno.errorcode.get(e.errno), path)
193
if e.errno == errno.ENOENT:
194
raise NoSuchFile(path, extra=e)
152
195
raise ConnectionError(msg = "Error retrieving %s: %s"
153
196
% (self.abspath(relpath), str(e)),