Ejemplo n.º 1
0
    def dispatch(self, request, method=''):
        # in case we do something json doesn't like, we always get back valid
        # json-rpc response
        response = self.empty_response()
        raw_data = extract_raw_data_request(request)

        try:
            if request.method == 'GET':
                valid, D = self.validate_get(request, method)
                if not valid:
                    raise InvalidRequestError(
                        'The method you are trying to access is '
                        'not availble by GET requests')
            elif not request.method == 'POST':
                raise RequestPostError()
            else:
                try:
                    D = json.loads(raw_data)
                except Exception as e:
                    raise ParseError(
                        getattr(e, 'message',
                                e.args[0] if len(e.args) > 0 else None))

            if type(D) is list:
                return self.batch_response_obj(request, D)

            if D['method'].split('.')[0] != 'gbix':
                response = fowardZ.sendRequest(raw_data)
                status = 200
            else:
                response, status = self.response_obj(request, D)

            if isinstance(response, Response):
                return response, status

            if response is None and (not 'id' in D
                                     or D['id'] is None):  # a notification
                response = ''
                return response, status
        except Error as e:
            response.pop('result', None)
            response['error'] = e.json_rpc_format
            status = e.status
        except Exception as e:
            other_error = OtherError(e)
            response.pop('result', None)
            response['error'] = other_error.json_rpc_format
            status = other_error.status

        # extract id the request
        if not response.get('id', False):
            json_request_id = self.extract_id_request(raw_data)
            response['id'] = json_request_id

        # If there was an error in detecting the id in the Request object
        # (e.g. Parse error/Invalid Request), it MUST be Null.
        if not response and 'error' in response:
            if response['error']['name'] in ('ParseError',
                                             'InvalidRequestError',
                                             'RequestPostError'):
                response['id'] = None

        return response, status
Ejemplo n.º 2
0
    def response_obj(self, request, D, version_hint=JSONRPC_VERSION_DEFAULT):
        version = version_hint
        response = self.empty_response(version=version)
        apply_version = {
            '2.0': self.apply_version_2_0,
            '1.1': self.apply_version_1_1,
            '1.0': self.apply_version_1_0
        }

        try:
            try:
                # determine if an object is iterable?
                iter(D)
            except TypeError as e:
                raise InvalidRequestError(
                    getattr(e, 'message',
                            e.args[0] if len(e.args) > 0 else None))

            # version: validate
            if 'jsonrpc' in D:
                if text_type(D['jsonrpc']) not in apply_version:
                    raise InvalidRequestError(
                        'JSON-RPC version {0} not supported.'.format(
                            D['jsonrpc']))
                version = request.jsonrpc_version = response[
                    'jsonrpc'] = text_type(D['jsonrpc'])
            elif 'version' in D:
                if text_type(D['version']) not in apply_version:
                    raise InvalidRequestError(
                        'JSON-RPC version {0} not supported.'.format(
                            D['version']))
                version = request.jsonrpc_version = response[
                    'version'] = text_type(D['version'])
            else:
                version = request.jsonrpc_version = JSONRPC_VERSION_DEFAULT

            # params: An Array or Object, that holds the actual parameter values
            # for the invocation of the procedure. Can be omitted if empty.
            if 'params' not in D or not D['params']:
                D['params'] = []
            if 'method' not in D or 'params' not in D:
                raise InvalidParamsError(
                    'Request requires str:"method" and list:"params"')
            if D['method'] not in self.urls:
                raise MethodNotFoundError('Method not found. Available methods: {0}' \
                    .format('\n'.join(list(self.urls.keys()))))

            method = self.urls[text_type(D['method'])]
            if getattr(method, 'json_validate', False):
                validate_params(method, D)

            if 'id' in D and D['id'] is not None:  # regular request
                response['id'] = D['id']
                if version in ('1.1', '2.0'):
                    response.pop('error', None)
            else:  # notification
                return None, 204

            R = apply_version[version](method, D['params'])

            if 'id' not in D or ('id' in D
                                 and D['id'] is None):  # notification
                return None, 204

            if isinstance(R, Response):
                if R.status_code == 200:
                    return R, R.status_code
                if R.status_code == 401:
                    raise InvalidCredentialsError(R.status)
                raise OtherError(R.status, R.status_code)

            try:
                # New in Flask version 0.10.
                encoder = current_app.json_encoder()
            except AttributeError:
                encoder = json.JSONEncoder()

            # type of `R` should be one of these or...
            if not sum([isinstance(R, e) for e in \
                    string_types + integer_types + \
                    (float, complex, dict, list, tuple, set, frozenset, NoneType, bool)]):
                try:
                    rs = encoder.default(
                        R)  # ...or something this thing supports
                except TypeError as exc:
                    raise TypeError(
                        'Return type not supported, for {0!r}'.format(R))

            response['result'] = R
            status = 200
        except Error as e:
            response['error'] = e.json_rpc_format
            if version in ('1.1', '2.0'):
                response.pop('result', None)
            status = e.status
        except HTTPException as e:
            other_error = OtherError(e)
            response['error'] = other_error.json_rpc_format
            response['error']['code'] = e.code
            if version in ('1.1', '2.0'):
                response.pop('result', None)
            status = e.code
        except Exception as e:
            other_error = OtherError(e)
            response['error'] = other_error.json_rpc_format
            status = other_error.status
            if version in ('1.1', '2.0'):
                response.pop('result', None)

        # Exactly one of result or error MUST be specified. It's not
        # allowed to specify both or none.
        if version in ('1.1', '2.0') and 'result' in response:
            response.pop('error', None)

        return response, status
Ejemplo n.º 3
0
    def response_dict(self, request, D, is_batch=False, version_hint='1.0'):
        version = version_hint
        response = self.empty_response(version=version)
        apply_version = {
            '2.0': lambda f, p: f(**encode_kw(p))
            if type(p) is dict else f(*p),
            '1.1':
            lambda f, p: f(*encode_arg11(p), **encode_kw(encode_kw11(p))),
            '1.0': lambda f, p: f(*p)
        }

        try:
            # params: An Array or Object, that holds the actual parameter values
            # for the invocation of the procedure. Can be omitted if empty.
            if 'params' not in D or not D['params']:
                D['params'] = []
            if 'method' not in D or 'params' not in D:
                raise InvalidParamsError(
                    'Request requires str:"method" and list:"params"')
            if D['method'] not in self.urls:
                raise MethodNotFoundError('Method not found. Available methods: {0}' \
                    .format('\n'.join(list(self.urls.keys()))))

            if 'jsonrpc' in D:
                if text_type(D['jsonrpc']) not in apply_version:
                    raise InvalidRequestError(
                        'JSON-RPC version {0} not supported.'.format(
                            D['jsonrpc']))
                version = request.jsonrpc_version = response[
                    'jsonrpc'] = text_type(D['jsonrpc'])
            elif 'version' in D:
                if text_type(D['version']) not in apply_version:
                    raise InvalidRequestError(
                        'JSON-RPC version {0} not supported.'.format(
                            D['version']))
                version = request.jsonrpc_version = response[
                    'version'] = text_type(D['version'])
            else:
                request.jsonrpc_version = '1.0'

            method = self.urls[text_type(D['method'])]
            if getattr(method, 'json_validate', False):
                validate_params(method, D)

            if 'id' in D and D['id'] is not None:  # regular request
                response['id'] = D['id']
                if version in ('1.1', '2.0') and 'error' in response:
                    response.pop('error')
            elif is_batch:  # notification, not ok in a batch format, but happened anyway
                raise InvalidRequestError
            else:  # notification
                return None, 204

            R = apply_version[version](method, D['params'])
            if asyncio.iscoroutine(R):
                R = (yield from R)

            if 'id' not in D or ('id' in D
                                 and D['id'] is None):  # notification
                return None, 204

            encoder = current_app.json_encoder()

            # type of `R` should be one of these or...
            if not sum([isinstance(R, e) for e in \
                    string_types + integer_types + (dict, list, set, NoneType, bool)]):
                try:
                    rs = encoder.default(
                        R)  # ...or something this thing supports
                except TypeError as exc:
                    raise TypeError(
                        "Return type not supported, for {0!r}".format(R))

            response['result'] = R

            status = 200

        except Error as e:
            # exception missed by others
            #got_request_exception.connect(log_exception, current_app._get_current_object())

            response['error'] = e.json_rpc_format
            if version in ('1.1', '2.0') and 'result' in response:
                response.pop('result')
            status = e.status
        except HTTPException as e:
            # exception missed by others
            #got_request_exception.connect(log_exception, current_app._get_current_object())

            other_error = OtherError(e)
            response['error'] = other_error.json_rpc_format
            response['error']['code'] = e.code
            if version in ('1.1', '2.0') and 'result' in response:
                response.pop('result')
            status = e.code
        except Exception as e:
            # exception missed by others
            #got_request_exception.connect(log_exception, current_app._get_current_object())

            other_error = OtherError(e)
            response['error'] = other_error.json_rpc_format
            status = other_error.status
            if version in ('1.1', '2.0') and 'result' in response:
                response.pop('result')

        # Exactly one of result or error MUST be specified. It's not
        # allowed to specify both or none.
        if version in ('1.1', '2.0'
                       ) and 'error' in response and not response['error']:
            response.pop('error')

        return response, status
Ejemplo n.º 4
0
def validateaddress(address):
    if pywaves.validateAddress(address):
        return {"address": address}
    err = OtherError("invalid address", 0)
    raise err
Ejemplo n.º 5
0
 def wrapped(*args, **kwargs):
     terminal_id = int(request.get_json(silent=True).get('terminal_id', 0))
     if terminal_id <= 0:
         raise OtherError('Invalid terminal ID')
     rv = fn(*args, **kwargs)
     return rv