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
예제 #3
0
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