From: Ben Darnell Date: Sun, 4 May 2014 23:05:07 +0000 (-0400) Subject: Allow ipv6 in simple_httpclient by default. X-Git-Tag: v4.0.0b1~62 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=602f40dab771715b06bb1cbd5bcc4a0eb746f2db;p=thirdparty%2Ftornado.git Allow ipv6 in simple_httpclient by default. Improve connection error handling (especially for SelectIOLoop). --- diff --git a/tornado/iostream.py b/tornado/iostream.py index c29494e2e..e6885b6a7 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -970,8 +970,9 @@ class IOStream(BaseIOStream): # an error state before the socket becomes writable, so # in that case a connection failure would be handled by the # error path in _handle_events instead of here. - gen_log.warning("Connect error on fd %s: %s", - self.socket.fileno(), errno.errorcode[err]) + if self._connect_future is None: + gen_log.warning("Connect error on fd %s: %s", + self.socket.fileno(), errno.errorcode[err]) self.close() return if self._connect_callback is not None: @@ -1132,6 +1133,10 @@ class SSLIOStream(IOStream): return super(SSLIOStream, self).connect(address, callback=None) def _handle_connect(self): + # Call the superclass method to check for errors. + super(SSLIOStream, self)._handle_connect() + if self.closed(): + return # When the connection is complete, wrap the socket for SSL # traffic. Note that we do this by overriding _handle_connect # instead of by passing a callback to super().connect because @@ -1149,7 +1154,6 @@ class SSLIOStream(IOStream): server_hostname=self._server_hostname, do_handshake_on_connect=False) self._add_io_state(old_state) - super(SSLIOStream, self)._handle_connect() def read_from_fd(self): if self._ssl_accepting: diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index 06d2ca801..2d90b0470 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -206,12 +206,10 @@ class _HTTPConnection(httputil.HTTPMessageDelegate): host = host[1:-1] self.parsed_hostname = host # save final host for _on_connect - if request.allow_ipv6: - af = socket.AF_UNSPEC - else: - # We only try the first IP we get from getaddrinfo, - # so restrict to ipv4 by default. + if request.allow_ipv6 is False: af = socket.AF_INET + else: + af = socket.AF_UNSPEC ssl_options = self._get_ssl_options(self.parsed.scheme) diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index e8349ed7e..e1a1b4205 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -254,12 +254,12 @@ class SimpleHTTPClientTestMixin(object): raise url = self.get_url("/hello").replace("localhost", "[::1]") - # ipv6 is currently disabled by default and must be explicitly requested - self.http_client.fetch(url, self.stop) + # ipv6 is currently enabled by default but can be disabled + self.http_client.fetch(url, self.stop, allow_ipv6=False) response = self.wait() self.assertEqual(response.code, 599) - self.http_client.fetch(url, self.stop, allow_ipv6=True) + self.http_client.fetch(url, self.stop) response = self.wait() self.assertEqual(response.body, b"Hello world!") diff --git a/tornado/test/tcpclient_test.py b/tornado/test/tcpclient_test.py index 7a9882e85..48099c66b 100644 --- a/tornado/test/tcpclient_test.py +++ b/tornado/test/tcpclient_test.py @@ -20,11 +20,10 @@ from contextlib import closing import socket from tornado.concurrent import Future -from tornado.log import gen_log from tornado.netutil import bind_sockets, Resolver from tornado.tcpclient import TCPClient, _Connector from tornado.tcpserver import TCPServer -from tornado.testing import AsyncTestCase, bind_unused_port, gen_test, ExpectLog +from tornado.testing import AsyncTestCase, bind_unused_port, gen_test from tornado.test.util import skipIfNoIPv6, unittest # Fake address families for testing. Used in place of AF_INET @@ -80,8 +79,7 @@ class TCPClientTest(AsyncTestCase): self.do_test_connect(socket.AF_INET, '127.0.0.1') def test_connect_ipv4_dual(self): - with ExpectLog(gen_log, 'Connect error', required=False): - self.do_test_connect(socket.AF_INET, 'localhost') + self.do_test_connect(socket.AF_INET, 'localhost') @skipIfNoIPv6 def test_connect_ipv6_ipv6(self): @@ -91,8 +89,7 @@ class TCPClientTest(AsyncTestCase): def test_connect_ipv6_dual(self): if Resolver.configured_class().__name__.endswith('TwistedResolver'): self.skipTest('TwistedResolver does not support multiple addresses') - with ExpectLog(gen_log, 'Connect error', required=False): - self.do_test_connect(socket.AF_INET6, 'localhost') + self.do_test_connect(socket.AF_INET6, 'localhost') def test_connect_unspec_ipv4(self): self.do_test_connect(socket.AF_UNSPEC, '127.0.0.1') @@ -108,9 +105,8 @@ class TCPClientTest(AsyncTestCase): def test_refused_ipv4(self): sock, port = bind_unused_port() sock.close() - with ExpectLog(gen_log, 'Connect error'): - with self.assertRaises(IOError): - yield self.client.connect('127.0.0.1', port) + with self.assertRaises(IOError): + yield self.client.connect('127.0.0.1', port) class TestConnectorSplit(unittest.TestCase):