Example #1
0
 def test_retry_read_zero(self):
     """ No second chances on read timeouts, by default """
     error = ReadTimeoutError(None, "/", "read timed out")
     retry = Retry(read=0)
     with pytest.raises(MaxRetryError) as e:
         retry.increment(method='GET', error=error)
     assert e.value.reason == error
Example #2
0
 def test_retry_higher_total_loses(self):
     """ A lower connect timeout than the total is honored """
     error = ConnectTimeoutError()
     retry = Retry(connect=2, total=3)
     retry = retry.increment(error=error)
     retry = retry.increment(error=error)
     with pytest.raises(MaxRetryError):
         retry.increment(error=error)
Example #3
0
 def test_retry_higher_total_loses_vs_read(self):
     """ A lower read timeout than the total is honored """
     error = ReadTimeoutError(None, "/", "read timed out")
     retry = Retry(read=2, total=3)
     retry = retry.increment(method='GET', error=error)
     retry = retry.increment(method='GET', error=error)
     with pytest.raises(MaxRetryError):
         retry.increment(method='GET', error=error)
Example #4
0
 def test_retry_both_specified(self):
     """Total can win if it's lower than the connect value"""
     error = ConnectTimeoutError()
     retry = Retry(connect=3, total=2)
     retry = retry.increment(error=error)
     retry = retry.increment(error=error)
     with pytest.raises(MaxRetryError) as e:
         retry.increment(error=error)
     assert e.value.reason == error
Example #5
0
 def test_status_counter(self):
     resp = HTTPResponse(status=400)
     retry = Retry(status=2)
     retry = retry.increment(response=resp)
     retry = retry.increment(response=resp)
     with pytest.raises(MaxRetryError) as e:
         retry.increment(response=resp)
     assert str(e.value.reason) == ResponseError.SPECIFIC_ERROR.format(
         status_code=400)
Example #6
0
 def test_string(self):
     """ Retry string representation looks the way we expect """
     retry = Retry()
     assert str(
         retry
     ) == 'Retry(total=10, connect=None, read=None, redirect=None, status=None)'
     for _ in range(3):
         retry = retry.increment(method='GET')
     assert str(
         retry
     ) == 'Retry(total=7, connect=None, read=None, redirect=None, status=None)'
 def test_retries(self):
     fp = BytesIO(b'')
     resp = HTTPResponse(fp)
     assert resp.retries is None
     retry = Retry()
     resp = HTTPResponse(fp, retries=retry)
     assert resp.retries == retry
    def test_too_many_redirects(self):
        http = PoolManager()
        self.addCleanup(http.clear)

        try:
            r = http.request('GET',
                             '%s/redirect' % self.base_url,
                             fields={
                                 'target':
                                 '%s/redirect?target=%s/' %
                                 (self.base_url, self.base_url)
                             },
                             retries=1)
            self.fail("Failed to raise MaxRetryError exception, returned %r" %
                      r.status)
        except MaxRetryError:
            pass

        try:
            r = http.request('GET',
                             '%s/redirect' % self.base_url,
                             fields={
                                 'target':
                                 '%s/redirect?target=%s/' %
                                 (self.base_url, self.base_url)
                             },
                             retries=Retry(total=None, redirect=1))
            self.fail("Failed to raise MaxRetryError exception, returned %r" %
                      r.status)
        except MaxRetryError:
            pass
Example #9
0
    def test_connect_timeout(self):
        url = '/'
        host, port = TARPIT_HOST, 80
        timeout = Timeout(connect=SHORT_TIMEOUT)

        # Pool-global timeout
        pool = HTTPConnectionPool(host, port, timeout=timeout)
        self.addCleanup(pool.close)
        conn = pool._get_conn()
        self.assertRaises(ConnectTimeoutError, pool._make_request, conn, 'GET', url)

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

        # Request-specific connection timeouts
        big_timeout = Timeout(read=LONG_TIMEOUT, connect=LONG_TIMEOUT)
        pool = HTTPConnectionPool(host, port, timeout=big_timeout, retries=False)
        self.addCleanup(pool.close)
        conn = pool._get_conn()
        self.assertRaises(ConnectTimeoutError,
                          pool._make_request,
                          conn, 'GET', url,
                          timeout=timeout)

        pool._put_conn(conn)
        self.assertRaises(ConnectTimeoutError, pool.request, 'GET', url, timeout=timeout)
Example #10
0
    def test_retry_total_none(self):
        """ if Total is none, connect error should take precedence """
        error = ConnectTimeoutError()
        retry = Retry(connect=2, total=None)
        retry = retry.increment(error=error)
        retry = retry.increment(error=error)
        with pytest.raises(MaxRetryError) as e:
            retry.increment(error=error)
        assert e.value.reason == error

        error = ReadTimeoutError(None, "/", "read timed out")
        retry = Retry(connect=2, total=None)
        retry = retry.increment(method='GET', error=error)
        retry = retry.increment(method='GET', error=error)
        retry = retry.increment(method='GET', error=error)
        assert not retry.is_exhausted()
Example #11
0
    def test_method_whitelist_with_status_forcelist(self):
        # Falsey method_whitelist means to retry on any method.
        retry = Retry(status_forcelist=[500], method_whitelist=None)
        assert retry.is_retry('GET', status_code=500)
        assert retry.is_retry('POST', status_code=500)

        # Criteria of method_whitelist and status_forcelist are ANDed.
        retry = Retry(status_forcelist=[500], method_whitelist=['POST'])
        assert not retry.is_retry('GET', status_code=500)
        assert retry.is_retry('POST', status_code=500)
Example #12
0
 def test_connection_error_retries(self):
     """ ECONNREFUSED error should raise a connection error, with retries """
     port = find_unused_port()
     pool = HTTPConnectionPool(self.host, port)
     try:
         pool.request('GET', '/', retries=Retry(connect=3))
         self.fail("Should have failed with a connection error.")
     except MaxRetryError as e:
         self.assertEqual(type(e.reason), NewConnectionError)
    def test_retries_wrong_whitelist(self):
        """HTTP response w/ status code not in whitelist shouldn't be retried"""
        retry = Retry(total=1, status_forcelist=[202])

        with PoolManager() as http:
            resp = http.request('GET',
                                '%s/successful_retry' % self.base_url,
                                headers={'test-name': 'test_wrong_whitelist'},
                                retries=retry)
            self.assertEqual(resp.status, 418)
    def test_read_retries(self):
        """ Should retry for status codes in the whitelist """
        retry = Retry(read=1, status_forcelist=[418])

        with PoolManager() as http:
            resp = http.request('GET',
                                '%s/successful_retry' % self.base_url,
                                headers={'test-name': 'test_read_retries'},
                                retries=retry)
            self.assertEqual(resp.status, 200)
Example #15
0
 def test_backoff_reset_after_redirect(self):
     retry = Retry(total=100, redirect=5, backoff_factor=0.2)
     retry = retry.increment(method='GET')
     retry = retry.increment(method='GET')
     assert retry.get_backoff_time() == 0.4
     redirect_response = HTTPResponse(status=302,
                                      headers={'location': 'test'})
     retry = retry.increment(method='GET', response=redirect_response)
     assert retry.get_backoff_time() == 0
     retry = retry.increment(method='GET')
     retry = retry.increment(method='GET')
     assert retry.get_backoff_time() == 0.4
    def test_default_method_whitelist_retried(self):
        """ urllib3 should retry methods in the default method whitelist """
        retry = Retry(total=1, status_forcelist=[418])

        with PoolManager() as http:
            resp = http.request(
                'OPTIONS',
                '%s/successful_retry' % self.base_url,
                headers={'test-name': 'test_default_whitelist'},
                retries=retry)
            self.assertEqual(resp.status, 200)
    def test_read_total_retries(self):
        """ HTTP response w/ status code in the whitelist should be retried """
        headers = {'test-name': 'test_read_total_retries'}
        retry = Retry(total=1, status_forcelist=[418])

        with PoolManager() as http:
            resp = http.request('GET',
                                '%s/successful_retry' % self.base_url,
                                headers=headers,
                                retries=retry)
            self.assertEqual(resp.status, 200)
    def test_retry_return_in_response(self):
        headers = {'test-name': 'test_retry_return_in_response'}
        retry = Retry(total=2, status_forcelist=[418])

        with PoolManager() as http:
            resp = http.request('GET',
                                '%s/successful_retry' % self.base_url,
                                headers=headers,
                                retries=retry)
            self.assertEqual(resp.status, 200)
            self.assertEqual(resp.retries.total, 1)
            self.assertEqual(resp.retries.history, (RequestHistory(
                'GET', '/successful_retry', None, 418, None), ))
    def test_retries_wrong_method_list(self):
        """Method not in our whitelist should not be retried, even if code matches"""
        headers = {'test-name': 'test_wrong_method_whitelist'}
        retry = Retry(total=1,
                      status_forcelist=[418],
                      method_whitelist=['POST'])

        with PoolManager() as http:
            resp = http.request('GET',
                                '%s/successful_retry' % self.base_url,
                                headers=headers,
                                retries=retry)
            self.assertEqual(resp.status, 418)
    def test_raise_on_status(self):
        http = PoolManager()
        self.addCleanup(http.clear)

        try:
            # the default is to raise
            r = http.request('GET',
                             '%s/status' % self.base_url,
                             fields={'status': '500 Internal Server Error'},
                             retries=Retry(total=1,
                                           status_forcelist=range(500, 600)))
            self.fail("Failed to raise MaxRetryError exception, returned %r" %
                      r.status)
        except MaxRetryError:
            pass

        try:
            # raise explicitly
            r = http.request('GET',
                             '%s/status' % self.base_url,
                             fields={'status': '500 Internal Server Error'},
                             retries=Retry(total=1,
                                           status_forcelist=range(500, 600),
                                           raise_on_status=True))
            self.fail("Failed to raise MaxRetryError exception, returned %r" %
                      r.status)
        except MaxRetryError:
            pass

        # don't raise
        r = http.request('GET',
                         '%s/status' % self.base_url,
                         fields={'status': '500 Internal Server Error'},
                         retries=Retry(total=1,
                                       status_forcelist=range(500, 600),
                                       raise_on_status=False))

        self.assertEqual(r.status, 500)
Example #21
0
    def test_history(self):
        retry = Retry(total=10, method_whitelist=frozenset(['GET', 'POST']))
        assert retry.history == tuple()
        connection_error = ConnectTimeoutError('conntimeout')
        retry = retry.increment('GET', '/test1', None, connection_error)
        history = (RequestHistory('GET', '/test1', connection_error, None,
                                  None), )
        assert retry.history == history

        read_error = ReadTimeoutError(None, "/test2", "read timed out")
        retry = retry.increment('POST', '/test2', None, read_error)
        history = (RequestHistory('GET', '/test1', connection_error, None,
                                  None),
                   RequestHistory('POST', '/test2', read_error, None, None))
        assert retry.history == history

        response = HTTPResponse(status=500)
        retry = retry.increment('GET', '/test3', response, None)
        history = (RequestHistory('GET', '/test1', connection_error, None,
                                  None),
                   RequestHistory('POST', '/test2', read_error, None, None),
                   RequestHistory('GET', '/test3', None, 500, None))
        assert retry.history == history
    def test_raise_on_redirect(self):
        http = PoolManager()
        self.addCleanup(http.clear)

        r = http.request('GET',
                         '%s/redirect' % self.base_url,
                         fields={
                             'target':
                             '%s/redirect?target=%s/' %
                             (self.base_url, self.base_url)
                         },
                         retries=Retry(total=None,
                                       redirect=1,
                                       raise_on_redirect=False))

        self.assertEqual(r.status, 303)
    def test_retry_reuse_safe(self):
        """ It should be possible to reuse a Retry object across requests """
        headers = {'test-name': 'test_retry_safe'}
        retry = Retry(total=1, status_forcelist=[418])

        with PoolManager() as http:
            resp = http.request('GET',
                                '%s/successful_retry' % self.base_url,
                                headers=headers,
                                retries=retry)
            self.assertEqual(resp.status, 200)
            resp = http.request('GET',
                                '%s/successful_retry' % self.base_url,
                                headers=headers,
                                retries=retry)
            self.assertEqual(resp.status, 200)
    def test_retries_put_filehandle(self):
        """HTTP PUT retry with a file-like object should not timeout"""
        retry = Retry(total=3, status_forcelist=[418])
        # httplib reads in 8k chunks; use a larger content length
        content_length = 65535
        data = b'A' * content_length
        uploaded_file = io.BytesIO(data)
        headers = {
            'test-name': 'test_retries_put_filehandle',
            'Content-Length': str(content_length)
        }

        with PoolManager() as http:
            resp = http.urlopen('PUT',
                                '%s/successful_retry' % self.base_url,
                                headers=headers,
                                retries=retry,
                                body=uploaded_file,
                                redirect=False)
            self.assertEqual(resp.status, 200)
    def test_redirect_put_file(self):
        """PUT with file object should work with a redirection response"""
        retry = Retry(total=3, status_forcelist=[418])
        # httplib reads in 8k chunks; use a larger content length
        content_length = 65535
        data = b'A' * content_length
        uploaded_file = io.BytesIO(data)
        headers = {
            'test-name': 'test_redirect_put_file',
            'Content-Length': str(content_length)
        }
        url = '%s/redirect?target=/echo&status=307' % self.base_url

        with PoolManager() as http:
            resp = http.urlopen('PUT',
                                url,
                                headers=headers,
                                retries=retry,
                                body=uploaded_file)
            self.assertEqual(resp.status, 200)
            self.assertEqual(resp.data, data)
    def test_disabled_retry(self):
        """ Disabled retries should disable redirect handling. """
        with PoolManager() as http:
            r = http.request('GET',
                             '%s/redirect' % self.base_url,
                             fields={'target': '/'},
                             retries=False)
            self.assertEqual(r.status, 303)

            r = http.request('GET',
                             '%s/redirect' % self.base_url,
                             fields={'target': '/'},
                             retries=Retry(redirect=False))
            self.assertEqual(r.status, 303)

            self.assertRaises(NewConnectionError,
                              http.request,
                              'GET',
                              'http://thishostdoesnotexist.invalid/',
                              timeout=0.001,
                              retries=False)
Example #27
0
 def test_parse_retry_after(self, value, expected):
     retry = Retry()
     assert retry.parse_retry_after(value) == expected
Example #28
0
 def test_parse_retry_after_invalid(self, value):
     retry = Retry()
     with pytest.raises(InvalidHeader):
         retry.parse_retry_after(value)
Example #29
0
    def test_retry_default(self):
        """ If no value is specified, should retry connects 3 times """
        retry = Retry()
        assert retry.total == 10
        assert retry.connect is None
        assert retry.read is None
        assert retry.redirect is None

        error = ConnectTimeoutError()
        retry = Retry(connect=1)
        retry = retry.increment(error=error)
        with pytest.raises(MaxRetryError):
            retry.increment(error=error)

        retry = Retry(connect=1)
        retry = retry.increment(error=error)
        assert not retry.is_exhausted()

        assert Retry(0).raise_on_redirect
        assert not Retry(False).raise_on_redirect
Example #30
0
 def test_retry_method_not_in_whitelist(self):
     error = ReadTimeoutError(None, "/", "read timed out")
     retry = Retry()
     with pytest.raises(ReadTimeoutError):
         retry.increment(method='POST', error=error)