-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresilient_requests.py
71 lines (53 loc) · 1.93 KB
/
resilient_requests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# -*- coding: utf-8 -*-
from builtins import super
import requests
import sys
from requests.exceptions import HTTPError
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
DEFAULT_TIMEOUT = 295 # seconds
TOTAL_RETRIES = 5
DEBUG_FLAG = False
def exception_handler(exception_type, exception, traceback, debug_hook=sys.excepthook):
if DEBUG_FLAG:
debug_hook(exception_type, exception, traceback)
else:
print("%s: %s" % (exception_type.__name__, exception))
sys.excepthook = exception_handler
class TimeoutHTTPAdapter(HTTPAdapter):
def __init__(self, *args, **kwargs):
self.timeout = DEFAULT_TIMEOUT
if "timeout" in kwargs:
self.timeout = kwargs["timeout"]
del kwargs["timeout"]
super().__init__(*args, **kwargs)
def send(self, request, **kwargs):
timeout = kwargs.get("timeout")
if timeout is None:
kwargs["timeout"] = self.timeout
return super().send(request, **kwargs)
retry_strategy = Retry(total=TOTAL_RETRIES,
backoff_factor=2,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "POST"])
adapter = TimeoutHTTPAdapter(max_retries=retry_strategy)
def expanded_raise_for_status(res):
"""
Take a "requests" response object and expand the raise_for_status method to return more helpful errors
:param res:
:return: None
"""
try:
res.raise_for_status()
except HTTPError as e:
try:
raise HTTPError('{}\nReason: {}'.format(str(e), res.json()['message']))
except ValueError:
raise e
return
def resilient_requests(func, *args, **kwargs):
with requests.Session() as session:
session.mount("https://", adapter)
response = getattr(session, func)(*args, **kwargs)
expanded_raise_for_status(response)
return response