66from typing import Any
77
88import httpx
9- import requests
109from tenacity import after_log , before_log , retry , retry_if_exception_type , stop_after_attempt , wait_exponential
1110
1211logger = logging .getLogger (__file__ )
1312
1413
1514def request_with_retry (
1615 attempts : int = 3 , status_codes_to_retry : list [int ] | None = None , ** kwargs : Any
17- ) -> requests .Response :
16+ ) -> httpx .Response :
1817 """
1918 Executes an HTTP request with a configurable exponential backoff retry on failures.
2019
@@ -35,26 +34,11 @@ def request_with_retry(
3534 # Sending an HTTP request with custom timeout in seconds
3635 res = request_with_retry(method="GET", url="https://example.com", timeout=5)
3736
38- # Sending an HTTP request with custom authorization handling
39- class CustomAuth(requests.auth.AuthBase):
40- def __call__(self, r):
41- r.headers["authorization"] = "Basic <my_token_here>"
42- return r
43-
44- res = request_with_retry(method="GET", url="https://example.com", auth=CustomAuth())
45-
46- # All of the above combined
47- res = request_with_retry(
48- method="GET",
49- url="https://example.com",
50- auth=CustomAuth(),
51- attempts=10,
52- status_codes_to_retry=[408, 503],
53- timeout=5
54- )
37+ # Sending an HTTP request with custom headers
38+ res = request_with_retry(method="GET", url="https://example.com", headers={"Authorization": "Bearer <token>"})
5539
5640 # Sending a POST request
57- res = request_with_retry(method="POST", url="https://example.com", data ={"key": "value"}, attempts=10)
41+ res = request_with_retry(method="POST", url="https://example.com", json ={"key": "value"}, attempts=10)
5842
5943 # Retry all 5xx status codes
6044 res = request_with_retry(method="GET", url="https://example.com", status_codes_to_retry=list(range(500, 600)))
@@ -66,9 +50,9 @@ def __call__(self, r):
6650 List of HTTP status codes that will trigger a retry.
6751 When param is `None`, HTTP 408, 418, 429 and 503 will be retried.
6852 :param kwargs:
69- Optional arguments that `request` accepts.
53+ Optional arguments that `httpx.Client. request` accepts.
7054 :returns:
71- The `Response` object.
55+ The `httpx. Response` object.
7256 """
7357
7458 if status_codes_to_retry is None :
@@ -77,20 +61,21 @@ def __call__(self, r):
7761 @retry (
7862 reraise = True ,
7963 wait = wait_exponential (),
80- retry = retry_if_exception_type ((requests .HTTPError , TimeoutError )),
64+ retry = retry_if_exception_type ((httpx .HTTPError , TimeoutError )),
8165 stop = stop_after_attempt (attempts ),
8266 before = before_log (logger , logging .DEBUG ),
8367 after = after_log (logger , logging .DEBUG ),
8468 )
85- def run () -> requests .Response :
69+ def run () -> httpx .Response :
8670 timeout = kwargs .pop ("timeout" , 10 )
87- res = requests .request (** kwargs , timeout = timeout )
71+ with httpx .Client () as client :
72+ res = client .request (** kwargs , timeout = timeout )
8873
89- if res .status_code in status_codes_to_retry :
90- # We raise only for the status codes that must trigger a retry
91- res .raise_for_status ()
74+ if res .status_code in status_codes_to_retry :
75+ # We raise only for the status codes that must trigger a retry
76+ res .raise_for_status ()
9277
93- return res
78+ return res
9479
9580 res = run ()
9681 # We raise here too in case the request failed with a status code that
0 commit comments