File: //home/arjun/projects/buyercall/buyercall/blueprints/email/utils/request_dispatcher.py
# __author__ = "Jayashankar Ramakrishnan"
from functools import wraps
import requests
class RequestDispatcher:
@staticmethod
def retry(exceptions, tries=4, delay=3, backoff=3):
"""
Retry if there is an exception.
Retry calling the decorated function using an exponential backoff. If all retries fail,
the exception is simply raised. https://www.calazan.com/retry-decorator-for-python-3/
:param exceptions: The exception to check. may be a tuple of exceptions to check.
(ConnectionError, requests.Timeout) -> Retry the request if it throws a ConnectionError or Timeout
(Exception) -> Retry if any exception occurs.
:param tries: Number of times to try before giving up.
:param delay: Initial delay between retries in seconds.
:param backoff: Backoff multiplier (value of 3 will triple the delay each retry).
:return:
"""
def deco_retry(f):
@wraps(f)
def f_retry(*args, **kwargs):
# set defaults
tries2 = tries
delay2 = delay
backoff2 = backoff
mod_tries, mod_delay = tries2, delay2
attempt = 1
while mod_tries > 1:
try:
return f(*args, **kwargs)
except exceptions as err:
attempt += 1
mod_tries -= 1
mod_delay *= backoff2
return f(*args, **kwargs)
return f_retry # true decorator
return deco_retry
@staticmethod
def head_request(url, headers=None, params=None):
"""
send a head request to given url and return the response
:param url: string (fully qualified URL)
:param headers: dict
:param params: dict
"""
try:
r = requests.head(url=url, params=params, headers=headers)
resp = {'success': True if r.ok else False, 'status_code': r.status_code, 'data': r.text,
'message': 'success'}
except Exception as err:
resp = {'success': False, 'status_code': 500, 'message': str(err), 'data': ''}
return resp
@staticmethod
# @retry(Exception) # Exception = retry on any Exception
def request_retry(url, headers=None, params=None, data=None, method='get', timeout=(10, 120)):
"""
calls requests with the retry decorator
:param url: string (fully qualified URL)
:param headers: dict
:param params: dict
:param data: dict
:param method: string (get, post, delete, patch, head, options)
:param timeout: The value in seconds for connect and read timeouts respectively.
:return: dict
status codes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
"""
if not headers:
headers = {}
response = {}
try:
r = requests.request(method=method, url=url, headers=headers, params=params, data=data,
timeout=timeout, verify=False)
if r.ok:
response = {'success': True, 'status_code': r.status_code, 'message': 'success', 'data': r.text}
else:
# HTTPError will be raised for 4XX client errors or 5XX server errors. No raise if successful 2XX
r.raise_for_status()
except requests.HTTPError as http_err:
response = {'success': False, 'status_code': r.status_code, 'message': str(http_err), 'data': ''}
except Exception as err: # timeouts, server errors, etc.
response = {'success': False, 'status_code': 500, 'message': str(err), 'data': ''}
return response