async def test_raise_on_status(self, backend, anyio_backend): with PoolManager(backend=backend) as http: with pytest.raises(MaxRetryError): # the default is to raise r = await http.request( "GET", "%s/status" % self.base_url, fields={"status": "500 Internal Server Error"}, retries=Retry(total=1, status_forcelist=range(500, 600)), ) with pytest.raises(MaxRetryError): # raise explicitly r = await 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), ) # don't raise r = await 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), ) assert r.status == 500
async def test_disabled_retry(self, backend, anyio_backend): """ Disabled retries should disable redirect handling. """ with PoolManager(backend=backend) as http: r = await http.request( "GET", "%s/redirect" % self.base_url, fields={"target": "/"}, retries=False, ) assert r.status == 303 r = await http.request( "GET", "%s/redirect" % self.base_url, fields={"target": "/"}, retries=Retry(redirect=False), ) assert r.status == 303 with pytest.raises(NewConnectionError): await http.request( "GET", "http://thishostdoesnotexist.invalid/", timeout=0.001, retries=False, )
async def test_too_many_redirects(self, backend, anyio_backend): with PoolManager(backend=backend) as http: with pytest.raises(MaxRetryError): await http.request( "GET", "%s/redirect" % self.base_url, fields={ "target": "%s/redirect?target=%s/" % (self.base_url, self.base_url) }, retries=1, ) with pytest.raises(MaxRetryError): await 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), )
async def test_raise_on_redirect(self, backend, anyio_backend): with PoolManager(backend=backend) as http: r = await 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), ) assert r.status == 303
async def test_redirect_cross_host_set_removed_headers( self, backend, anyio_backend): with PoolManager(backend=backend) as http: r = await http.request( "GET", "%s/redirect" % self.base_url, fields={"target": "%s/headers" % self.base_url_alt}, headers={ "X-API-Secret": "foo", "Authorization": "bar" }, retries=Retry(remove_headers_on_redirect=["X-API-Secret"]), ) assert r.status == 200 data = json.loads(r.data.decode("utf-8")) assert "X-API-Secret" not in data assert data["Authorization"] == "bar" r = await http.request( "GET", "%s/redirect" % self.base_url, fields={"target": "%s/headers" % self.base_url_alt}, headers={ "x-api-secret": "foo", "authorization": "bar" }, retries=Retry(remove_headers_on_redirect=["X-API-Secret"]), ) assert r.status == 200 data = json.loads(r.data.decode("utf-8")) assert "x-api-secret" not in data assert "X-API-Secret" not in data assert data["Authorization"] == "bar"
async def test_read_retries(self, backend, anyio_backend): """ Should retry for status codes in the whitelist """ retry = Retry(read=1, status_forcelist=[418]) with PoolManager(backend=backend) as http: resp = await http.request( "GET", "%s/successful_retry" % self.base_url, headers={ "test-name": _test_name("test_read_retries", backend, anyio_backend) }, retries=retry, ) assert resp.status == 200
async def test_retries_wrong_whitelist(self, backend, anyio_backend): """HTTP response w/ status code not in whitelist shouldn't be retried""" headers = { "test-name": _test_name("test_wrong_whitelist", backend, anyio_backend) } retry = Retry(total=1, status_forcelist=[202]) with PoolManager(backend=backend) as http: resp = await http.request( "GET", "%s/successful_retry" % self.base_url, retries=retry, headers=headers, ) assert resp.status == 418
async def test_read_total_retries(self, backend, anyio_backend): """ HTTP response w/ status code in the whitelist should be retried """ headers = { "test-name": _test_name("test_read_total_retries", backend, anyio_backend) } retry = Retry(total=1, status_forcelist=[418]) with PoolManager(backend=backend) as http: resp = await http.request( "GET", "%s/successful_retry" % self.base_url, headers=headers, retries=retry, ) assert resp.status == 200
async def test_default_method_whitelist_retried(self, backend, anyio_backend): """Hip should retry methods in the default method whitelist""" headers = { "test-name": _test_name("test_default_whitelist", backend, anyio_backend) } retry = Retry(total=1, status_forcelist=[418]) with PoolManager(backend=backend) as http: resp = await http.request( "OPTIONS", "%s/successful_retry" % self.base_url, headers=headers, retries=retry, ) assert resp.status == 200
async def test_retry_return_in_response(self, backend, anyio_backend): headers = { "test-name": _test_name("test_retry_return_in_response", backend, anyio_backend) } retry = Retry(total=2, status_forcelist=[418]) with PoolManager(backend=backend) as http: resp = await http.request( "GET", "%s/successful_retry" % self.base_url, headers=headers, retries=retry, ) assert resp.status == 200 assert resp.retries.total == 1 assert resp.retries.history == (RequestHistory( "GET", "/successful_retry", None, 418, None), )
async def test_retries_wrong_method_list(self, backend, anyio_backend): """Method not in our whitelist should not be retried, even if code matches""" headers = { "test-name": _test_name("test_wrong_method_whitelist", backend, anyio_backend) } retry = Retry(total=1, status_forcelist=[418], method_whitelist=["POST"]) with PoolManager(backend=backend) as http: resp = await http.request( "GET", "%s/successful_retry" % self.base_url, headers=headers, retries=retry, ) assert resp.status == 418
async def test_redirect_put_file(self, backend, anyio_backend): """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(backend=backend) as http: resp = await http.urlopen("PUT", url, headers=headers, retries=retry, body=uploaded_file) assert resp.status == 200 assert resp.data == data
async def test_retries_put_filehandle(self, backend, anyio_backend): """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(backend=backend) as http: resp = await http.urlopen( "PUT", "%s/successful_retry" % self.base_url, headers=headers, retries=retry, body=uploaded_file, redirect=False, ) assert resp.status == 200
async def test_retry_reuse_safe(self, backend, anyio_backend): """ It should be possible to reuse a Retry object across requests """ headers = { "test-name": _test_name("test_retry_safe", backend, anyio_backend) } retry = Retry(total=1, status_forcelist=[418]) with PoolManager(backend=backend) as http: resp = await http.request( "GET", "%s/successful_retry" % self.base_url, headers=headers, retries=retry, ) assert resp.status == 200 resp = await http.request( "GET", "%s/successful_retry" % self.base_url, headers=headers, retries=retry, ) assert resp.status == 200