def test_connect_timeout(self):
        url = '/sleep?seconds=0.005'
        timeout = Timeout(connect=0.001)

        # Pool-global timeout
        pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout)
        conn = pool._get_conn()
        yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url))

        # Retries
        retries = Retry(connect=0)
        yield From(self.aioAssertRaises(MaxRetryError, pool.request, 'GET', url,
                          retries=retries))

        # Request-specific connection timeouts
        big_timeout = Timeout(read=0.2, connect=0.2)
        pool = HTTPConnectionPool(TARPIT_HOST, self.port,
                                  timeout=big_timeout, retries=False)
        conn = pool._get_conn()
        yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET',
                          url, timeout=timeout))

        pool._put_conn(conn)
        yield From(self.aioAssertRaises(ConnectTimeoutError, pool.request, 'GET', url,
                          timeout=timeout))
Example #2
0
    def tst_enhanced_timeout(self):
        def new_pool(timeout, cert_reqs='CERT_REQUIRED'):
            https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port,
                                             timeout=timeout,
                                             retries=False,
                                             cert_reqs=cert_reqs)
            return https_pool

        https_pool = new_pool(Timeout(connect=0.001))
        conn = https_pool._new_conn()
        try:
            yield From(https_pool.request('GET', '/'))
        except ConnectTimeoutError as e:
            pass
        except Exception as e:
            pass
        except:
            pass
        else:
            self.fail('connect timeout error not raised')
        yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool._make_request, conn, 'GET', '/'))

        https_pool = new_pool(Timeout(connect=5))
        yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/',
                          timeout=Timeout(connect=0.001)))

        t = Timeout(total=None)
        https_pool = new_pool(t)
        conn = https_pool._new_conn()
        yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/',
                          timeout=Timeout(total=None, connect=0.001)))
Example #3
0
    def tst_https_timeout(self):
        timeout = Timeout(connect=0.001)
        https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port,
                                          timeout=timeout, retries=False,
                                          cert_reqs='CERT_REQUIRED')

        timeout = Timeout(total=None, connect=0.001)
        https_pool = HTTPSConnectionPool(TARPIT_HOST, self.port,
                                         timeout=timeout, retries=False,
                                         cert_reqs='CERT_REQUIRED')
        yield From(self.aioAssertRaises(ConnectTimeoutError, https_pool.request, 'GET', '/'))

        timeout = Timeout(read=0.001)
        https_pool = HTTPSConnectionPool(self.host, self.port,
                                         timeout=timeout, retries=False,
                                         cert_reqs='CERT_REQUIRED')
        https_pool.ca_certs = DEFAULT_CA
        https_pool.assert_fingerprint = 'CC:45:6A:90:82:F7FF:C0:8218:8e:' \
                                        '7A:F2:8A:D7:1E:07:33:67:DE'
        url = '/sleep?seconds=0.005'
        try:
            yield From(https_pool.request('GET', url))
        except ReadTimeoutError as e:
            pass
        else:
            self.fail('ReadTimeoutError was not raised')

        timeout = Timeout(total=None)
        https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout,
                                         cert_reqs='CERT_NONE')
        yield From(https_pool.request('GET', '/'))
    def test_invalid_timeouts(self):
        try:
            Timeout(total=-1)
            self.fail("negative value should throw exception")
        except ValueError as e:
            self.assertTrue('less than' in str(e))
        try:
            Timeout(connect=2, total=-1)
            self.fail("negative value should throw exception")
        except ValueError as e:
            self.assertTrue('less than' in str(e))

        try:
            Timeout(read=-1)
            self.fail("negative value should throw exception")
        except ValueError as e:
            self.assertTrue('less than' in str(e))

        # Booleans are allowed also by socket.settimeout and converted to the
        # equivalent float (1.0 for True, 0.0 for False)
        Timeout(connect=False, read=True)

        try:
            Timeout(read="foo")
            self.fail("string value should not be allowed")
        except ValueError as e:
            self.assertTrue('int or float' in str(e))
    def test_timeout_success(self):
        timeout = Timeout(connect=3, read=5, total=None)
        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
        yield From(pool.request('GET', '/'))
        # This should not raise a "Timeout already started" error
        yield From(pool.request('GET', '/'))

        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
        # This should also not raise a "Timeout already started" error
        yield From(pool.request('GET', '/'))

        timeout = Timeout(total=None)
        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
        yield From(pool.request('GET', '/'))
    def test_delayed_body_read_timeout(self):
        timed_out = Event()

        def socket_handler(listener):
            sock = listener.accept()[0]
            buf = b''
            body = 'Hi'
            while not buf.endswith(b'\r\n\r\n'):
                buf = sock.recv(65536)
            sock.send(('HTTP/1.1 200 OK\r\n'
                       'Content-Type: text/plain\r\n'
                       'Content-Length: %d\r\n'
                       '\r\n' % len(body)).encode('utf-8'))

            timed_out.wait()
            sock.send(body.encode('utf-8'))
            sock.close()

        self._start_server(socket_handler)
        pool = HTTPConnectionPool(self.host, self.port)

        response = yield From(
            pool.urlopen('GET',
                         '/',
                         retries=0,
                         preload_content=False,
                         timeout=Timeout(connect=1, read=0.1)))
        try:
            self.aioAssertRaises(ReadTimeoutError, response.read)
        finally:
            timed_out.set()
    def test_total_timeout(self):
        url = '/sleep?seconds=0.005'

        timeout = Timeout(connect=3, read=5, total=0.001)
        pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout)
        conn = pool._get_conn()
        yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url))

        # This will get the socket to raise an EAGAIN on the read
        timeout = Timeout(connect=3, read=0)
        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
        conn = pool._get_conn()
        yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', url))

        # The connect should succeed and this should hit the read timeout
        timeout = Timeout(connect=3, read=5, total=0.002)
        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
        conn = pool._get_conn()
        yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn, 'GET', url))
 def test_timeout_reset(self):
     """ If the read timeout isn't set, socket timeout should reset """
     url = '/sleep?seconds=0.005'
     timeout = Timeout(connect=0.001)
     pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
     conn = pool._get_conn()
     try:
         yield From(pool._make_request(conn, 'GET', url))
     except ReadTimeoutError:
         self.fail("This request shouldn't trigger a read timeout.")
Example #9
0
 def test_tunnel(self):
     """ test the _tunnel behavior """
     timeout = Timeout(total=None)
     https_pool = HTTPSConnectionPool(self.host, self.port, timeout=timeout,
                                      cert_reqs='CERT_NONE')
     conn = https_pool._new_conn()
     try:
         conn.set_tunnel(self.host, self.port)
     except AttributeError: # python 2.6
         conn._set_tunnel(self.host, self.port)
     conn._tunnel = mock.Mock(return_value=iter([None, None, None]))
     yield From(https_pool._make_request(conn, 'GET', '/'))
     conn._tunnel.assert_called_once_with()
    def test_tunnel(self):
        # note the actual httplib.py has no tests for this functionality
        timeout = Timeout(total=None)
        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
        conn = pool._get_conn()
        try:
            conn.set_tunnel(self.host, self.port)
        except AttributeError: # python 2.6
            conn._set_tunnel(self.host, self.port)

        conn._tunnel = mock.Mock(return_value=None)
        yield From(pool._make_request(conn, 'GET', '/'))
        conn._tunnel.assert_called_once_with()

        # test that it's not called when tunnel is not set
        timeout = Timeout(total=None)
        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout)
        conn = pool._get_conn()

        conn._tunnel = mock.Mock(return_value=None)
        yield From(pool._make_request(conn, 'GET', '/'))
        self.assertEqual(conn._tunnel.called, False)
    def test_timeout_elapsed(self, current_time):
        current_time.return_value = TIMEOUT_EPOCH
        timeout = Timeout(total=3)
        self.assertRaises(TimeoutStateError, timeout.get_connect_duration)

        timeout.start_connect()
        self.assertRaises(TimeoutStateError, timeout.start_connect)

        current_time.return_value = TIMEOUT_EPOCH + 2
        self.assertEqual(timeout.get_connect_duration(), 2)
        current_time.return_value = TIMEOUT_EPOCH + 37
        self.assertEqual(timeout.get_connect_duration(), 37)
    def test_timeout(self):
        """ Requests should time out when expected """
        url = '/sleep?seconds=0.002'
        timeout = Timeout(read=0.001)

        # Pool-global timeout
        pool = HTTPConnectionPool(self.host, self.port, timeout=timeout, retries=False)

        conn = pool._get_conn()
        yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request,
                          conn, 'GET', url))
        pool._put_conn(conn)

        time.sleep(0.02) # Wait for server to start receiving again. :(

        yield From(self.aioAssertRaises(ReadTimeoutError, pool.request, 'GET', url))

        # Request-specific timeouts should raise errors
        pool = HTTPConnectionPool(self.host, self.port, timeout=0.1, retries=False)

        conn = pool._get_conn()
        yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request,
                          conn, 'GET', url, timeout=timeout))
        pool._put_conn(conn)

        time.sleep(0.02) # Wait for server to start receiving again. :(

        yield From(self.aioAssertRaises(ReadTimeoutError, pool.request,
                          'GET', url, timeout=timeout))

        # Timeout int/float passed directly to request and _make_request should
        # raise a request timeout
        yield From(self.aioAssertRaises(ReadTimeoutError, pool.request,
                          'GET', url, timeout=0.001))
        conn = pool._new_conn()
        yield From(self.aioAssertRaises(ReadTimeoutError, pool._make_request, conn,
                          'GET', url, timeout=0.001))
        pool._put_conn(conn)

        # Timeout int/float passed directly to _make_request should not raise a
        # request timeout if it's a high value
        yield From(pool.request('GET', url, timeout=1))
    def tst_timeout_errors_cause_retries(self):
        def socket_handler(listener):
            sock_timeout = listener.accept()[0]

            # Wait for a second request before closing the first socket.
            sock = listener.accept()[0]
            sock_timeout.close()

            # Second request.
            buf = b''
            while not buf.endswith(b'\r\n\r\n'):
                buf += sock.recv(65536)

            # Now respond immediately.
            body = 'Response 2'
            sock.send(('HTTP/1.1 200 OK\r\n'
                       'Content-Type: text/plain\r\n'
                       'Content-Length: %d\r\n'
                       '\r\n'
                       '%s' % (len(body), body)).encode('utf-8'))

            sock.close()

        # In situations where the main thread throws an exception, the server
        # thread can hang on an accept() call. This ensures everything times
        # out within 1 second. This should be long enough for any socket
        # operations in the test suite to complete
        default_timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(1)

        try:
            self._start_server(socket_handler)
            t = Timeout(connect=0.1, read=0.1)
            pool = HTTPConnectionPool(self.host, self.port, timeout=t)

            response = yield From(pool.request('GET', '/', retries=1))
            self.assertEqual(response.status, 200)
            self.assertEqual((yield From(response.data), b'Response 2'))
        finally:
            socket.setdefaulttimeout(default_timeout)
    def test_timeout(self, current_time):
        timeout = Timeout(total=3)

        # make 'no time' elapse
        timeout = self._make_time_pass(seconds=0, timeout=timeout,
                                       time_mock=current_time)
        self.assertEqual(timeout.read_timeout, 3)
        self.assertEqual(timeout.connect_timeout, 3)

        timeout = Timeout(total=3, connect=2)
        self.assertEqual(timeout.connect_timeout, 2)

        timeout = Timeout()
        self.assertEqual(timeout.connect_timeout, Timeout.DEFAULT_TIMEOUT)

        # Connect takes 5 seconds, leaving 5 seconds for read
        timeout = Timeout(total=10, read=7)
        timeout = self._make_time_pass(seconds=5, timeout=timeout,
                                       time_mock=current_time)
        self.assertEqual(timeout.read_timeout, 5)

        # Connect takes 2 seconds, read timeout still 7 seconds
        timeout = Timeout(total=10, read=7)
        timeout = self._make_time_pass(seconds=2, timeout=timeout,
                                       time_mock=current_time)
        self.assertEqual(timeout.read_timeout, 7)

        timeout = Timeout(total=10, read=7)
        self.assertEqual(timeout.read_timeout, 7)

        timeout = Timeout(total=None, read=None, connect=None)
        self.assertEqual(timeout.connect_timeout, None)
        self.assertEqual(timeout.read_timeout, None)
        self.assertEqual(timeout.total, None)

        timeout = Timeout(5)
        self.assertEqual(timeout.total, 5)
    def test_ssl_read_timeout(self):
        timed_out = Event()

        def socket_handler(listener):
            sock = listener.accept()[0]
            ssl_sock = ssl.wrap_socket(sock,
                                       server_side=True,
                                       keyfile=DEFAULT_CERTS['keyfile'],
                                       certfile=DEFAULT_CERTS['certfile'],
                                       ca_certs=DEFAULT_CA)

            buf = b''
            while not buf.endswith(b'\r\n\r\n'):
                buf += ssl_sock.recv(65536)

            # Send incomplete message (note Content-Length)
            ssl_sock.send(('HTTP/1.1 200 OK\r\n'
                           'Content-Type: text/plain\r\n'
                           'Content-Length: 10\r\n'
                           '\r\n'
                           'Hi-').encode('utf-8'))
            timed_out.wait()

            sock.close()
            ssl_sock.close()

        self._start_server(socket_handler)
        pool = HTTPSConnectionPool(self.host, self.port)

        response = yield From(
            pool.urlopen('GET',
                         '/',
                         retries=0,
                         preload_content=False,
                         timeout=Timeout(connect=1, read=0.5)))
        try:
            self.aioAssertRaises(ReadTimeoutError, response.read)
        finally:
            timed_out.set()
 def test_none_total_applies_connect(self):
     url = '/sleep?seconds=0.005'
     timeout = Timeout(total=None, connect=0.001)
     pool = HTTPConnectionPool(TARPIT_HOST, self.port, timeout=timeout)
     conn = pool._get_conn()
     yield From(self.aioAssertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url))
 def test_timeout_str(self):
     timeout = Timeout(connect=1, read=2, total=3)
     self.assertEqual(str(timeout), "Timeout(connect=1, read=2, total=3)")
     timeout = Timeout(connect=1, read=None, total=3)
     self.assertEqual(str(timeout), "Timeout(connect=1, read=None, total=3)")