128
127
('urllib,http', dict(_activity_server=ActivityHTTPServer,
129
128
_transport=_urllib.HttpTransport_urllib,)),
130
if features.pycurl.available():
131
activity_scenarios.append(
132
('pycurl,http', dict(_activity_server=ActivityHTTPServer,
133
_transport=PyCurlTransport,)),)
131
134
if features.HTTPSServerFeature.available():
135
# FIXME: Until we have a better way to handle self-signed certificates
136
# (like allowing them in a test specific authentication.conf for
137
# example), we need some specialized pycurl/urllib transport for tests.
139
from bzrlib.tests import (
142
class HTTPS_urllib_transport(_urllib.HttpTransport_urllib):
144
def __init__(self, base, _from_transport=None):
145
super(HTTPS_urllib_transport, self).__init__(
146
base, _from_transport=_from_transport,
147
ca_certs=ssl_certs.build_path('ca.crt'))
132
149
activity_scenarios.append(
133
150
('urllib,https', dict(_activity_server=ActivityHTTPSServer,
134
_transport=_urllib.HttpTransport_urllib,)),)
135
if features.pycurl.available():
136
activity_scenarios.append(
137
('pycurl,http', dict(_activity_server=ActivityHTTPServer,
138
_transport=PyCurlTransport,)),)
139
if features.HTTPSServerFeature.available():
140
from bzrlib.tests import (
143
# FIXME: Until we have a better way to handle self-signed
144
# certificates (like allowing them in a test specific
145
# authentication.conf for example), we need some specialized pycurl
146
# transport for tests.
151
_transport=HTTPS_urllib_transport,)),)
152
if features.pycurl.available():
147
153
class HTTPS_pycurl_transport(PyCurlTransport):
149
155
def __init__(self, base, _from_transport=None):
254
260
self.assertEqual('basic', scheme)
255
261
self.assertEqual('realm="Thou should not pass"', remainder)
263
def test_build_basic_header_with_long_creds(self):
264
handler = _urllib2_wrappers.BasicAuthHandler()
265
user = 'user' * 10 # length 40
266
password = 'password' * 5 # length 40
267
header = handler.build_auth_header(
268
dict(user=user, password=password), None)
269
# https://bugs.launchpad.net/bzr/+bug/1606203 was caused by incorrectly
270
# creating a header value with an embedded '\n'
271
self.assertFalse('\n' in header)
257
273
def test_basic_extract_realm(self):
258
274
scheme, remainder = self.parse_header(
259
275
'Basic realm="Thou should not pass"',
282
298
self.req_handler = RequestHandler(None, None, None)
284
300
def assertRanges(self, ranges, header, file_size):
285
self.assertEquals(ranges,
301
self.assertEqual(ranges,
286
302
self.req_handler._parse_ranges(header, file_size))
288
304
def test_simple_range(self):
378
394
_transport = property(_get_pycurl_maybe)
381
class TestHttpUrls(tests.TestCase):
383
# TODO: This should be moved to authorization tests once they
386
def test_url_parsing(self):
388
url = http.extract_auth('http://example.com', f)
389
self.assertEqual('http://example.com', url)
390
self.assertEqual(0, len(f.credentials))
391
url = http.extract_auth(
392
'http://user:pass@example.com/bzr/bzr.dev', f)
393
self.assertEqual('http://example.com/bzr/bzr.dev', url)
394
self.assertEqual(1, len(f.credentials))
395
self.assertEqual([None, 'example.com', 'user', 'pass'],
399
397
class TestHttpTransportUrls(tests.TestCase):
400
398
"""Test the http urls."""
533
531
scenarios = vary_by_http_client_implementation()
535
533
def test_http_registered(self):
536
t = transport.get_transport('%s://foo.com/' % self._url_protocol)
534
t = transport.get_transport_from_url(
535
'%s://foo.com/' % self._url_protocol)
537
536
self.assertIsInstance(t, transport.Transport)
538
537
self.assertIsInstance(t, self._transport)
551
550
self.start_server(server)
552
551
url = server.get_url()
553
552
# FIXME: needs a cleanup -- vila 20100611
554
http_transport = transport.get_transport(url)
553
http_transport = transport.get_transport_from_url(url)
555
554
code, response = http_transport._post('abc def end-of-body')
557
556
server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
668
667
_req_handler_class = BadStatusRequestHandler
670
super(TestBadStatusServer, self).setUp()
671
# See https://bugs.launchpad.net/bzr/+bug/1451448 for details.
672
# TD;LR: Running both a TCP client and server in the same process and
673
# thread uncovers a race in python. The fix is to run the server in a
674
# different process. Trying to fix yet another race here is not worth
675
# the effort. -- vila 2015-09-06
676
if 'HTTP/1.0' in self.id():
677
raise tests.TestSkipped(
678
'Client/Server in the same process and thread can hang')
670
680
def test_http_has(self):
671
681
t = self.get_readonly_transport()
672
self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
682
self.assertRaises((errors.ConnectionError, errors.ConnectionReset,
683
errors.InvalidHttpResponse),
674
686
def test_http_get(self):
675
687
t = self.get_readonly_transport()
676
self.assertRaises(errors.InvalidHttpResponse, t.get, 'foo/bar')
688
self.assertRaises((errors.ConnectionError, errors.ConnectionReset,
689
errors.InvalidHttpResponse),
679
693
class InvalidStatusRequestHandler(http_server.TestingHTTPRequestHandler):
1156
1170
protocol_version=self._protocol_version)
1158
1172
def setUp(self):
1159
http_utils.TestCaseWithWebserver.setUp(self)
1173
super(TestLimitedRangeRequestServer, self).setUp()
1160
1174
# We need to manipulate ranges that correspond to real chunks in the
1161
1175
# response, so we build a content appropriately.
1162
1176
filler = ''.join(['abcdefghij' for x in range(102)])
1197
1211
def assertEvaluateProxyBypass(self, expected, host, no_proxy):
1198
1212
handler = _urllib2_wrappers.ProxyHandler()
1199
self.assertEquals(expected,
1213
self.assertEqual(expected,
1200
1214
handler.evaluate_proxy_bypass(host, no_proxy))
1202
1216
def test_empty_user(self):
1269
1283
self.no_proxy_host = self.server_host_port
1270
1284
# The secondary server is the proxy
1271
1285
self.proxy_url = self.get_secondary_url()
1286
if self._testing_pycurl():
1287
self.proxy_url = self.proxy_url.replace('+pycurl', '')
1273
1289
def _testing_pycurl(self):
1274
1290
# TODO: This is duplicated for lots of the classes in this file
1850
1867
def get_user_transport(self, user, password):
1851
self.overrideEnv('all_proxy', self.get_user_url(user, password))
1868
proxy_url = self.get_user_url(user, password)
1869
if self._testing_pycurl():
1870
proxy_url = proxy_url.replace('+pycurl', '')
1871
self.overrideEnv('all_proxy', proxy_url)
1852
1872
return TestAuth.get_user_transport(self, user, password)
1854
1874
def test_empty_pass(self):
1903
1923
server._url_protocol = self._url_protocol
1906
def test_open_bzrdir(self):
1926
def test_open_controldir(self):
1907
1927
branch = self.make_branch('relpath')
1908
1928
url = self.http_server.get_url() + 'relpath'
1909
bd = bzrdir.BzrDir.open(url)
1929
bd = controldir.ControlDir.open(url)
1910
1930
self.addCleanup(bd.transport.disconnect)
1911
1931
self.assertIsInstance(bd, _mod_remote.RemoteBzrDir)
1915
1935
# The 'readv' command in the smart protocol both sends and receives
1916
1936
# bulk data, so we use that.
1917
1937
self.build_tree(['data-file'])
1918
http_transport = transport.get_transport(self.http_server.get_url())
1938
http_transport = transport.get_transport_from_url(
1939
self.http_server.get_url())
1919
1940
medium = http_transport.get_smart_medium()
1920
1941
# Since we provide the medium, the url below will be mostly ignored
1921
1942
# during the test, as long as the path is '/'.
1929
1950
post_body = 'hello\n'
1930
1951
expected_reply_body = 'ok\x012\n'
1932
http_transport = transport.get_transport(self.http_server.get_url())
1953
http_transport = transport.get_transport_from_url(
1954
self.http_server.get_url())
1933
1955
medium = http_transport.get_smart_medium()
1934
1956
response = medium.send_http_smart_request(post_body)
1935
1957
reply_body = response.read()
1993
2015
self.assertIsInstance(r, type(t))
1994
2016
# Both transports share the some connection
1995
2017
self.assertEqual(t._get_connection(), r._get_connection())
2018
self.assertEqual('http://www.example.com/foo/subdir/', r.base)
1997
2020
def test_redirected_to_self_with_slash(self):
1998
2021
t = self._transport('http://www.example.com/foo')
2009
2032
r = t._redirected_to('http://www.example.com/foo',
2010
2033
'http://foo.example.com/foo/subdir')
2011
2034
self.assertIsInstance(r, type(t))
2035
self.assertEqual('http://foo.example.com/foo/subdir/',
2013
2038
def test_redirected_to_same_host_sibling_protocol(self):
2014
2039
t = self._transport('http://www.example.com/foo')
2015
2040
r = t._redirected_to('http://www.example.com/foo',
2016
2041
'https://www.example.com/foo')
2017
2042
self.assertIsInstance(r, type(t))
2043
self.assertEqual('https://www.example.com/foo/',
2019
2046
def test_redirected_to_same_host_different_protocol(self):
2020
2047
t = self._transport('http://www.example.com/foo')
2021
2048
r = t._redirected_to('http://www.example.com/foo',
2022
2049
'ftp://www.example.com/foo')
2023
self.assertNotEquals(type(r), type(t))
2050
self.assertNotEqual(type(r), type(t))
2051
self.assertEqual('ftp://www.example.com/foo/', r.external_url())
2053
def test_redirected_to_same_host_specific_implementation(self):
2054
t = self._transport('http://www.example.com/foo')
2055
r = t._redirected_to('http://www.example.com/foo',
2056
'https+urllib://www.example.com/foo')
2057
self.assertEqual('https://www.example.com/foo/', r.external_url())
2025
2059
def test_redirected_to_different_host_same_user(self):
2026
2060
t = self._transport('http://joe@www.example.com/foo')
2028
2062
'https://foo.example.com/foo')
2029
2063
self.assertIsInstance(r, type(t))
2030
2064
self.assertEqual(t._parsed_url.user, r._parsed_url.user)
2065
self.assertEqual('https://joe@foo.example.com/foo/', r.external_url())
2033
2068
class PredefinedRequestHandler(http_server.TestingHTTPRequestHandler):
2102
2137
def setUp(self):
2103
tests.TestCase.setUp(self)
2104
2138
self.server = self._activity_server(self._protocol_version)
2105
2139
self.server.start_server()
2140
self.addCleanup(self.server.stop_server)
2106
2141
_activities = {} # Don't close over self and create a cycle
2107
2142
def report_activity(t, bytes, direction):
2108
2143
count = _activities.get(direction, 0)
2110
2145
_activities[direction] = count
2111
2146
self.activities = _activities
2113
2147
# We override at class level because constructors may propagate the
2114
2148
# bound method and render instance overriding ineffective (an
2115
2149
# alternative would be to define a specific ui factory instead...)
2116
2150
self.overrideAttr(self._transport, '_report_activity', report_activity)
2117
self.addCleanup(self.server.stop_server)
2119
2152
def get_transport(self):
2120
2153
t = self._transport(self.server.get_url())