23
23
from warnings import warn
25
26
from bzrlib.transport import Transport, Server
26
27
from bzrlib.errors import (TransportNotPossible, NoSuchFile,
27
28
TransportError, ConnectionError)
28
29
from bzrlib.errors import BzrError, BzrCheckError
29
30
from bzrlib.branch import Branch
30
31
from bzrlib.trace import mutter
32
from bzrlib.ui import ui_factory
33
35
def extract_auth(url, password_manager):
36
38
password manager. Return the url, minus those auth parameters (which
39
assert url.startswith('http://') or url.startswith('https://')
40
scheme, host = url.split('//', 1)
42
host, path = host.split('/', 1)
48
auth, host = host.split('@', 1)
41
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
42
assert (scheme == 'http') or (scheme == 'https')
45
auth, netloc = netloc.split('@', 1)
50
47
username, password = auth.split(':', 1)
52
49
username, password = auth, None
54
host, port = host.split(':', 1)
56
# FIXME: if password isn't given, should we ask for it?
51
host = netloc.split(':', 1)[0]
54
username = urllib.unquote(username)
57
55
if password is not None:
58
username = urllib.unquote(username)
59
56
password = urllib.unquote(password)
60
password_manager.add_password(None, host, username, password)
61
url = scheme + '//' + host + port + path
58
password = ui_factory.get_password(prompt='HTTP %(user)@%(host) password',
59
user=username, host=host)
60
password_manager.add_password(None, host, username, password)
61
url = urlparse.urlunsplit((scheme, netloc, path, query, fragment))
65
class Request(urllib2.Request):
66
"""Request object for urllib2 that allows the method to be overridden."""
71
if self.method is not None:
74
return urllib2.Request.get_method(self)
77
def get_url(url, method=None):
66
mutter("get_url %s" % url)
79
mutter("get_url %s", url)
67
80
manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
68
81
url = extract_auth(url, manager)
69
82
auth_handler = urllib2.HTTPBasicAuthHandler(manager)
70
83
opener = urllib2.build_opener(auth_handler)
71
url_f = opener.open(url)
85
request = Request(url)
86
request.method = method
87
request.add_header('User-Agent', 'bzr/%s' % bzrlib.__version__)
88
response = opener.open(request)
74
92
class HttpTransport(Transport):
75
93
"""This is the transport agent for http:// access.
301
316
class TestingHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
303
318
def log_message(self, format, *args):
304
self.server.test_case.log("webserver - %s - - [%s] %s",
319
self.server.test_case.log('webserver - %s - - [%s] %s "%s" "%s"',
305
320
self.address_string(),
306
321
self.log_date_time_string(),
323
self.headers.get('referer', '-'),
324
self.headers.get('user-agent', '-'))
309
326
def handle_one_request(self):
310
327
"""Handle a single HTTP request.
350
368
class HttpServer(Server):
351
369
"""A test server for http transports."""
353
_HTTP_PORTS = range(13000, 0x8000)
355
371
def _http_start(self):
357
for port in self._HTTP_PORTS:
359
httpd = TestingHTTPServer(('localhost', port),
360
TestingHTTPRequestHandler,
362
except socket.error, e:
363
if e.args[0] == errno.EADDRINUSE:
365
print >>sys.stderr, "Cannot run webserver :-("
371
raise WebserverNotAvailable("Cannot run webserver :-( "
372
"no free ports in range %s..%s" %
373
(_HTTP_PORTS[0], _HTTP_PORTS[-1]))
373
httpd = TestingHTTPServer(('localhost', 0),
374
TestingHTTPRequestHandler,
376
host, port = httpd.socket.getsockname()
375
377
self._http_base_url = 'http://localhost:%s/' % port
376
378
self._http_starting.release()
377
379
httpd.socket.settimeout(0.1)
396
398
self._http_starting.release()
397
399
return self._http_base_url + remote_path
399
def log(self, *args, **kwargs):
401
def log(self, format, *args):
400
402
"""Capture Server log output."""
401
self.logs.append(args[3])
403
self.logs.append(format % args)
404
406
"""See bzrlib.transport.Server.setUp."""