class RestClient(RestClientInterface): '''Define concrete Adapter ''' _name = 'provider2' _pandapool = Provider2Pool() def __init__(self, *args, **kwargs): cherrypy.thread_data.client_obj = self if 'log' in kwargs: self._log = kwargs['log'] super().__init__(*args, **kwargs) def _logging(self, message: str, url: str = None, log_type: str = None) -> None: if self._log: api_config[self._name]['log'] = True if api_config[self._name]['log'] is False: return if not hasattr(self, 'logger'): self.logger = LibPool().logger logdata = {'connection_details': api_config[self._name]} if url: logdata['url'] = url if log_type is not None and log_type == 'error': self.logger.error(message, logdata) else: self.logger.info(message, logdata) def send_request(self, api_endpoint: str, data: dict = {}) -> dict: ac = api_config[self._name] url_start = '{}{}?'.format(ac['url'], api_endpoint) if '?' in api_endpoint: url_start = '{}&'.format(url_start[0:-1]) url = '{}token={}'.format(url_start, ac['auth_token']) try: if self._pandapool.request_permission: response = requests.get(url, data=to_json(data)) if response.status_code == 401: raise AuthenticationError(response.json()['error']) elif 'error' in response.json(): raise Exception(response.json()['error']) except AuthenticationError as e: error_message = 'Authentication error on Provider 1: {}'.format(e) self._logging(error_message, url, 'error') raise cherrypy.HTTPError(401, error_message) except Exception as e: error_message = 'Request to Provider 1 was not succesfull: {}'.format( e) self._logging(error_message, url, 'error') raise cherrypy.HTTPError(500, error_message) tools.check_request_timeout( ) # Application hook to return 408 if time is over return response.headers, response.json() def authenticate(self) -> None: # Provider 1 is always authenticated, hit lives matches to check it url = '{}{}'.format(api_config[self._name]['url'], 'lives') response = requests.get(url) if response.status_code == 401: return False def monitor(self) -> float: # Try to authenticate at REST endpoint start_time = time.perf_counter() if self.authenticate() is False: return False return time.perf_counter() - start_time
class RestClient(RestClientInterface): '''Define concrete Adapter ''' _name = 'provider1' _abiospool = Provider1Pool() def __init__(self, *args, **kwargs): cherrypy.thread_data.client_obj = self if 'log' in kwargs: self._log = kwargs['log'] super().__init__(*args, **kwargs) def _logging(self, message: str, url: str = None, log_type: str = None, log_data: dict = {}) -> None: if self._log: api_config[self._name]['log'] = True if api_config[self._name]['log'] is False: return if not hasattr(self, 'logger'): self.logger = LibPool().logger logdata = log_data logdata = { 'connection_details': api_config[self._name] } if url: logdata['url'] = url if log_type is not None and log_type == 'error': self.logger.error(message, logdata) else: self.logger.info(message, logdata) def send_request(self, api_endpoint: str, data: dict = {}) -> dict: auth_token = self._abiospool.auth_token if auth_token is None: # Auth token does not exists, get new one self.authenticate() auth_token = self._abiospool.auth_token if auth_token is None: error_message = 'Cannot connect to Provider 2' self._logging(error_message, log_type='error') raise cherrypy.HTTPError(401, error_message) ac = api_config[self._name] url_start = '{}{}?'.format(ac['url'], api_endpoint) if '?' in api_endpoint: url_start = '{}&'.format(url_start[0:-1]) url = '{}access_token={}'.format(url_start, auth_token) if self._abiospool.request_permission: response = requests.get(url, data=to_json(data)) if response.status_code == 401 and response.json()['error_description'] == 'Access token is not valid.': # Unauthorized -> authenticate & repeat request error_message = 'Provider 2 Unauthorized: {} {}'.format(response.json()['error_description'], auth_token) self._logging(error_message, url, 'error') info_message = 'Reconnect to Provider 2' self._logging(info_message) self.authenticate() response = requests.get(url, data=to_json(data)) tools.check_request_timeout() # Application hook to return 408 if time is over return response.headers, response.json() def authenticate(self) -> None: ac = api_config[self._name] auth_data = { 'grant_type': 'client_credentials', 'client_id': ac['client_id'], 'client_secret': ac['client_secret'] } headers = {'Content-Type': 'application/x-www-form-urlencoded'} url = '{}{}'.format(ac['url'], 'oauth/access_token') try: # Authenticate response = requests.post(url, data=auth_data, headers=headers) if 'error' in response.json(): raise AuthenticationError(response.json()['error_description']) self._abiospool.auth_token = response.json()['access_token'] except Exception as e: error_message = 'Authenticate to Provider 2 was not succesfull: {}'.format(e) self._logging(error_message, url, 'error') raise cherrypy.HTTPError(401, error_message) def monitor(self) -> float: # Try to authenticate at REST endpoint start_time = time.perf_counter() if self.authenticate() is False: return False return time.perf_counter() - start_time
class Invoker(object): def __init__(self): self.logger = LibPool().logger def setup_server(self): self._set_config() self._set_cherrypy_hooks() def _set_config(self): default_config = { 'tools.encode.on': True, 'tools.encode.encoding': 'utf-8', # Prevents CherryPy Checker: The Application mounted at '' has an empty config. 'checker.check_skipped_app_config': False, # Allow hooks 'tools.on_start_resource.on': True, 'tools.before_finalize.on': True, 'tools.before_error_response.on': True, 'tools.after_error_response.on': True, 'tools.on_end_request.on': True } cherrypy.config.update( toolz.dicttoolz.merge(app_config['cherrypy'], default_config)) def _set_cherrypy_hooks(self): cherrypy.tools.on_start_resource = cherrypy.Tool( 'on_start_resource', app_tools.on_start_resource_wrapper) cherrypy.tools.before_finalize = cherrypy.Tool( 'before_finalize', app_tools.before_finalize_wrapper) cherrypy.tools.before_error_response = cherrypy.Tool( 'before_error_response', app_tools.before_error_response_wrapper) cherrypy.tools.after_error_response = cherrypy.Tool( 'after_error_response', app_tools.after_error_response_wrapper) cherrypy.tools.on_end_request = cherrypy.Tool( 'on_end_request', app_tools.on_end_request_wrapper) def cli_cmd(self): self.setup_server() cherrypy.config.update({'engine.autoreload.on': True}) if platform.system() == 'Windows': # This enables Ctrl+C on Windows if hasattr(cherrypy.engine, 'signal_handler'): cherrypy.engine.signal_handler.subscribe() if hasattr(cherrypy.engine, 'console_control_handler'): cherrypy.engine.console_control_handler.subscribe() cherrypy.engine.start() if app_config['app_log_factory'] == 'gcp': self.logger.info( 'Starting Cherrypy server on "{}:{}" at "{}"\n'.format( app_config['cherrypy']['server.socket_host'], app_config['cherrypy']['server.socket_port'], datetime.strftime(datetime.utcnow(), '%Y-%m-%d %H:%M:%S'))) cherrypy.engine.block() def wsgi_cmd(self): self.setup_server() cherrypy.config.update({ 'environment': 'embedded', 'engine.autoreload.on': False }) cherrypy.server.unsubscribe() sys.stdout = sys.stderr def application(environ, start_response): return cherrypy.tree(environ, start_response) return application