def _call_method(self, ctx, request):
        """Calls given method with given params and returns it value."""
        method = self.method_data[request['method']]['method']
        params = request['params']
        result = None
        try:
            if isinstance(params, list):
                # Does it have enough arguments?
                if len(params) < self._man_args(method) - 1:
                    raise InvalidParamsError('not enough arguments')
                # Does it have too many arguments?
                if(not self._vargs(method) and len(params) >
                        self._max_args(method) - 1):
                    raise InvalidParamsError('too many arguments')

                result = method(ctx, *params)
            elif isinstance(params, dict):
                # Do not accept keyword arguments if the jsonrpc version is
                # not >=1.1.
                if request['jsonrpc'] < 11:
                    raise KeywordError

                result = method(ctx, **params)
            else:  # No params
                result = method(ctx)
        except JSONRPCError:
            raise
        except Exception as e:
            # log.exception('method %s threw an exception' % request['method'])
            # Exception was raised inside the method.
            newerr = JSONServerError()
            newerr.trace = traceback.format_exc()
            if len(e.args) == 1:
                newerr.data = repr(e.args[0])
            else:
                newerr.data = repr(e.args)
            raise newerr
        return result
    def __call__(self, environ, start_response):
        # Context object, equivalent to the perl impl CallContext
        ctx = MethodContext(self.userlog)
        ctx['client_ip'] = getIPAddress(environ)
        status = '500 Internal Server Error'

        try:
            body_size = int(environ.get('CONTENT_LENGTH', 0))
        except (ValueError):
            body_size = 0
        if environ['REQUEST_METHOD'] == 'OPTIONS':
            # we basically do nothing and just return headers
            status = '200 OK'
            rpc_result = ""
        else:
            request_body = environ['wsgi.input'].read(body_size)
            try:
                req = json.loads(request_body)
            except ValueError as ve:
                err = {
                    'error': {
                        'code': -32700,
                        'name': "Parse error",
                        'message': str(ve),
                    }
                }
                rpc_result = self.process_error(err, ctx, {'version': '1.1'})
            else:
                ctx['module'], ctx['method'] = req['method'].split('.')
                ctx['call_id'] = req['id']
                ctx['rpc_context'] = {
                    'call_stack': [{
                        'time': self.now_in_utc(),
                        'method': req['method']
                    }]
                }
                prov_action = {
                    'service': ctx['module'],
                    'method': ctx['method'],
                    'method_params': req['params']
                }
                ctx['provenance'] = [prov_action]
                try:
                    token = environ.get('HTTP_AUTHORIZATION')
                    # parse out the method being requested and check if it
                    # has an authentication requirement
                    method_name = req['method']
                    auth_req = self.method_authentication.get(
                        method_name, 'none')
                    if auth_req != 'none':
                        if token is None and auth_req == 'required':
                            err = JSONServerError()
                            err.data = (
                                'Authentication required for ' +
                                'AssemblyRAST ' +
                                'but no authentication header was passed')
                            raise err
                        elif token is None and auth_req == 'optional':
                            pass
                        else:
                            try:
                                user = self.auth_client.get_user(token)
                                ctx['user_id'] = user
                                ctx['authenticated'] = 1
                                ctx['token'] = token
                            except Exception, e:
                                if auth_req == 'required':
                                    err = JSONServerError()
                                    err.data = \
                                        "Token validation failed: %s" % e
                                    raise err
                    if (environ.get('HTTP_X_FORWARDED_FOR')):
                        self.log(
                            log.INFO, ctx, 'X-Forwarded-For: ' +
                            environ.get('HTTP_X_FORWARDED_FOR'))
                    self.log(log.INFO, ctx, 'start method')
                    rpc_result = self.rpc_service.call(ctx, req)
                    self.log(log.INFO, ctx, 'end method')
                    status = '200 OK'
                except JSONRPCError as jre:
                    err = {
                        'error': {
                            'code': jre.code,
                            'name': jre.message,
                            'message': jre.data
                        }
                    }
                    trace = jre.trace if hasattr(jre, 'trace') else None
                    rpc_result = self.process_error(err, ctx, req, trace)
                except Exception:
                    err = {
                        'error': {
                            'code': 0,
                            'name': 'Unexpected Server Error',
                            'message':
                            'An unexpected server error ' + 'occurred',
                        }
                    }
                    rpc_result = self.process_error(err, ctx, req,
                                                    traceback.format_exc())
Beispiel #3
0
    def __call__(self, environ, start_response):
        # Context object, equivalent to the perl impl CallContext
        ctx = MethodContext(self.userlog)
        ctx['client_ip'] = getIPAddress(environ)
        status = '500 Internal Server Error'

        try:
            body_size = int(environ.get('CONTENT_LENGTH', 0))
        except (ValueError):
            body_size = 0
        if environ['REQUEST_METHOD'] == 'OPTIONS':
            # we basically do nothing and just return headers
            status = '200 OK'
            rpc_result = ""
        else:
            request_body = environ['wsgi.input'].read(body_size)
            try:
                req = json.loads(request_body)
            except ValueError as ve:
                err = {
                    'error': {
                        'code': -32700,
                        'name': "Parse error",
                        'message': str(ve),
                    }
                }
                rpc_result = self.process_error(err, ctx, {'version': '1.1'})
            else:
                ctx['module'], ctx['method'] = req['method'].split('.')
                ctx['call_id'] = req['id']
                ctx['rpc_context'] = {
                    'call_stack': [{
                        'time': self.now_in_utc(),
                        'method': req['method']
                    }]
                }
                prov_action = {
                    'service': ctx['module'],
                    'method': ctx['method'],
                    'method_params': req['params']
                }
                ctx['provenance'] = [prov_action]
                try:
                    token = environ.get('HTTP_AUTHORIZATION')
                    # parse out the method being requested and check if it
                    # has an authentication requirement
                    method_name = req['method']
                    auth_req = self.method_authentication.get(
                        method_name, 'none')
                    if auth_req != 'none':
                        if token is None and auth_req == 'required':
                            err = JSONServerError()
                            err.data = (
                                'Authentication required for ' +
                                'omreegalozpathway_completeness ' +
                                'but no authentication header was passed')
                            raise err
                        elif token is None and auth_req == 'optional':
                            pass
                        else:
                            try:
                                user = self.auth_client.get_user(token)
                                ctx['user_id'] = user
                                ctx['authenticated'] = 1
                                ctx['token'] = token
                            except Exception as e:
                                if auth_req == 'required':
                                    err = JSONServerError()
                                    err.data = \
                                        "Token validation failed: %s" % e
                                    raise err
                    if (environ.get('HTTP_X_FORWARDED_FOR')):
                        self.log(
                            log.INFO, ctx, 'X-Forwarded-For: ' +
                            environ.get('HTTP_X_FORWARDED_FOR'))
                    self.log(log.INFO, ctx, 'start method')
                    rpc_result = self.rpc_service.call(ctx, req)
                    self.log(log.INFO, ctx, 'end method')
                    status = '200 OK'
                except JSONRPCError as jre:
                    err = {
                        'error': {
                            'code': jre.code,
                            'name': jre.message,
                            'message': jre.data
                        }
                    }
                    trace = jre.trace if hasattr(jre, 'trace') else None
                    rpc_result = self.process_error(err, ctx, req, trace)
                except Exception:
                    err = {
                        'error': {
                            'code': 0,
                            'name': 'Unexpected Server Error',
                            'message':
                            'An unexpected server error ' + 'occurred',
                        }
                    }
                    rpc_result = self.process_error(err, ctx, req,
                                                    traceback.format_exc())

        # print('Request method was %s\n' % environ['REQUEST_METHOD'])
        # print('Environment dictionary is:\n%s\n' % pprint.pformat(environ))
        # print('Request body was: %s' % request_body)
        # print('Result from the method call is:\n%s\n' % \
        #    pprint.pformat(rpc_result))

        if rpc_result:
            response_body = rpc_result
        else:
            response_body = ''

        response_headers = [('Access-Control-Allow-Origin', '*'),
                            ('Access-Control-Allow-Headers',
                             environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS',
                                         'authorization')),
                            ('content-type', 'application/json'),
                            ('content-length', str(len(response_body)))]
        start_response(status, response_headers)
        return [response_body.encode('utf8')]
Beispiel #4
0
    def __call__(self, environ, start_response):
        # Context object, equivalent to the perl impl CallContext
        ctx = MethodContext(self.userlog)
        ctx['client_ip'] = getIPAddress(environ)
        status = '500 Internal Server Error'

        try:
            body_size = int(environ.get('CONTENT_LENGTH', 0))
        except (ValueError):
            body_size = 0
        if environ['REQUEST_METHOD'] == 'OPTIONS':
            # we basically do nothing and just return headers
            status = '200 OK'
            rpc_result = ""
        else:
            request_body = environ['wsgi.input'].read(body_size)
            try:
                req = json.loads(request_body)
            except ValueError as ve:
                err = {
                    'error': {
                        'code': -32700,
                        'name': "Parse error",
                        'message': str(ve),
                    }
                }
                rpc_result = self.process_error(err, ctx, {'version': '1.1'})
            else:
                ctx['module'], ctx['method'] = req['method'].split('.')
                ctx['call_id'] = req['id']
                ctx['rpc_context'] = {
                    'call_stack': [{
                        'time': self.now_in_utc(),
                        'method': req['method']
                    }]
                }
                prov_action = {
                    'service': ctx['module'],
                    'method': ctx['method'],
                    'method_params': req['params']
                }
                ctx['provenance'] = [prov_action]
                try:
                    token = environ.get('HTTP_AUTHORIZATION')
                    # parse out the method being requested and check if it
                    # has an authentication requirement
                    method_name = req['method']
                    if method_name in async_run_methods:
                        method_name = async_run_methods[method_name][
                            0] + "." + async_run_methods[method_name][1]
                    if method_name in async_check_methods:
                        method_name = async_check_methods[method_name][
                            0] + "." + async_check_methods[method_name][1]
                    auth_req = self.method_authentication.get(
                        method_name, "none")
                    if auth_req != "none":
                        if token is None and auth_req == 'required':
                            err = JSONServerError()
                            err.data = "Authentication required for " + \
                                "Catalog but no authentication header was passed"
                            raise err
                        elif token is None and auth_req == 'optional':
                            pass
                        else:
                            try:
                                user, _, _ = \
                                    self.auth_client.validate_token(token)
                                ctx['user_id'] = user
                                ctx['authenticated'] = 1
                                ctx['token'] = token
                            except Exception, e:
                                if auth_req == 'required':
                                    err = JSONServerError()
                                    err.data = \
                                        "Token validation failed: %s" % e
                                    raise err
                    if (environ.get('HTTP_X_FORWARDED_FOR')):
                        self.log(
                            log.INFO, ctx, 'X-Forwarded-For: ' +
                            environ.get('HTTP_X_FORWARDED_FOR'))
                    method_name = req['method']
                    if method_name in async_run_methods or method_name in async_check_methods:
                        if method_name in async_run_methods:
                            orig_method_pair = async_run_methods[method_name]
                        else:
                            orig_method_pair = async_check_methods[method_name]
                        orig_method_name = orig_method_pair[
                            0] + '.' + orig_method_pair[1]
                        if 'required' != self.method_authentication.get(
                                orig_method_name, 'none'):
                            err = JSONServerError()
                            err.data = 'Async method ' + orig_method_name + ' should require ' + \
                                'authentication, but it has authentication level: ' + \
                                self.method_authentication.get(orig_method_name, 'none')
                            raise err
                        job_service_client = AsyncJobServiceClient(
                            token=ctx['token'])
                        if method_name in async_run_methods:
                            run_job_params = {
                                'method': orig_method_name,
                                'params': req['params']
                            }
                            if 'rpc_context' in ctx:
                                run_job_params['rpc_context'] = ctx[
                                    'rpc_context']
                            job_id = job_service_client.run_job(run_job_params)
                            respond = {
                                'version': '1.1',
                                'result': [job_id],
                                'id': req['id']
                            }
                            rpc_result = json.dumps(respond,
                                                    cls=JSONObjectEncoder)
                            status = '200 OK'
                        else:
                            job_id = req['params'][0]
                            job_state = job_service_client.check_job(job_id)
                            finished = job_state['finished']
                            if finished != 0 and 'error' in job_state and job_state[
                                    'error'] is not None:
                                err = {'error': job_state['error']}
                                rpc_result = self.process_error(
                                    err, ctx, req, None)
                            else:
                                respond = {
                                    'version': '1.1',
                                    'result': [job_state],
                                    'id': req['id']
                                }
                                rpc_result = json.dumps(respond,
                                                        cls=JSONObjectEncoder)
                                status = '200 OK'
                    elif method_name in sync_methods or (
                            method_name + '_async') not in async_run_methods:
                        self.log(log.INFO, ctx, 'start method')
                        rpc_result = self.rpc_service.call(ctx, req)
                        self.log(log.INFO, ctx, 'end method')
                        status = '200 OK'
                    else:
                        err = JSONServerError()
                        err.data = 'Method ' + method_name + ' cannot be run synchronously'
                        raise err
                except JSONRPCError as jre:
                    err = {
                        'error': {
                            'code': jre.code,
                            'name': jre.message,
                            'message': jre.data
                        }
                    }
                    trace = jre.trace if hasattr(jre, 'trace') else None
                    rpc_result = self.process_error(err, ctx, req, trace)
                except Exception, e:
                    err = {
                        'error': {
                            'code': 0,
                            'name': 'Unexpected Server Error',
                            'message':
                            'An unexpected server error ' + 'occurred',
                        }
                    }
                    rpc_result = self.process_error(err, ctx, req,
                                                    traceback.format_exc())