Source code for freshpy.api
# -*- coding: utf-8 -*-
"""
:Module: freshpy.api
:Synopsis: This module handles interactions with the Freshservice REST API
:Created By: Jeff Shurtliff
:Last Modified: Jeff Shurtliff
:Modified Date: 04 Jan 2022
"""
import json
import requests
from . import errors
from .utils import log_utils
# Initialize logging
logger = log_utils.initialize_logging(__name__)
[docs]def define_auth(api_key):
"""This function defines the authentication dictionary to use in API calls.
.. versionadded:: 1.0.0
"""
credentials = (api_key, 'X')
return credentials
[docs]def get_request_with_retries(fresh_object, uri, headers=None, return_json=True, verify_ssl=True):
"""This function performs a GET request and will retry several times if a failure occurs.
.. versionchanged:: 1.1.0
Added the ability to disable SSL verification on API calls.
.. versionadded:: 1.0.0
:param fresh_object: The instantiated :py:class:`freshpy.core.FreshPy` object.
:param uri: The URI to query
:type uri: string
:param headers: The HTTP headers to utilize in the REST API call
:type headers: dict, None
:param return_json: Determines if JSON data should be returned
:type return_json: bool
:param verify_ssl: Determines if SSL verification should occur (``True`` by default)
:type verify_ssl: bool
:returns: The JSON data from the response or the raw :py:mod:`requests` response.
:raises: :py:exc:`freshpy.errors.exceptions.APIConnectionError`
"""
# Define headers if not supplied
headers = define_headers() if not headers else headers
# Construct the credentials dictionary
credentials = define_auth(fresh_object.api_key)
# Construct the query URL
query_url = fresh_object.base_url + uri
# Perform the API call
retries, response = 0, None
while retries <= 5:
try:
response = requests.get(query_url, headers=headers, auth=credentials, verify=verify_ssl)
break
except Exception as exc_msg:
_report_failed_attempt(exc_msg, 'get', retries)
retries += 1
if retries == 6:
_raise_exception_for_repeated_timeouts()
pass
if return_json:
response = response.json()
return response
def _report_failed_attempt(_exc_msg, _request_type, _retries):
"""This function reports a failed API call that will be retried.
.. versionadded:: 1.0.0
:param _exc_msg: The exception that was raised within a try/except clause
:param _request_type: The type of API request (e.g. ``post``, ``put`` or ``get``)
:type _request_type: str
:param _retries: The attempt number for the API request
:type _retries: int
:returns: None
"""
_exc_name = type(_exc_msg).__name__
if 'connect' not in _exc_name.lower():
raise Exception(f"{_exc_name}: {_exc_msg}")
_current_attempt = f"(Attempt {_retries} of 5)"
_error_msg = f"The {_request_type.upper()} request has failed with the following exception: " + \
f"{_exc_name}: {_exc_msg} {_current_attempt}"
errors.handlers.eprint(f"{_error_msg}\n{_exc_name}: {_exc_msg}\n")
return
def _raise_exception_for_repeated_timeouts():
"""This function raises an exception when all API attempts (including) retries resulted in a timeout.
.. versionadded:: 1.0.0
:returns: None
:raises: :py:exc:`freshpy.errors.exceptions.APIConnectionError`
"""
_failure_msg = "The script was unable to complete successfully after five consecutive API timeouts. " + \
"Please run the script again or contact Freshservice Support for further assistance."
raise errors.exceptions.APIConnectionError(_failure_msg)