예제 #1
0
        def handle_rest(path_args, flask_request):
            """Handle /REST/ route. Query the database using get_rows or create transaction using compose_transaction."""
            url_action = flask_request.path.split('/')[-1]
            if url_action == 'compose':
                compose = True
            elif url_action == 'get':
                compose = False
            else:
                error = 'Invalid action "%s".' % url_action
                return flask.Response(error, 400, mimetype='application/json')

            # Get all arguments passed via URL.
            url_args = path_args.split('/')
            try:
                query_type = url_args.pop(0).lower()
            except IndexError:
                error = 'No query_type provided.'
                return flask.Response(error, 400, mimetype='application/json')
            # Check if message type or table name are valid.
            if (compose and query_type not in API_TRANSACTIONS) or \
               (not compose and query_type not in API_TABLES):
                error = 'No such query type in supported queries: "%s".' % query_type
                return flask.Response(error, 400, mimetype='application/json')

            # Parse the additional arguments.
            extra_args = flask_request.args.items()
            query_data = {}

            if compose:
                common_args = {}
                transaction_args = {}
                for (key, value) in extra_args:
                    # Determine value type.
                    try:
                        value = int(value)
                    except ValueError:
                        try:
                            value = float(value)
                        except ValueError:
                            pass
                    # Split keys into common and transaction-specific arguments. Discard the privkey.
                    if key in COMMONS_ARGS:
                        common_args[key] = value
                    elif key == 'privkey':
                        pass
                    else:
                        transaction_args[key] = value

                # Must have some additional transaction arguments.
                if not len(transaction_args):
                    error = 'No transaction arguments provided.'
                    return flask.Response(error, 400, mimetype='application/json')

                # Compose the transaction.
                try:
                    query_data = compose_transaction(db, name=query_type, params=transaction_args, **common_args)
                except (script.AddressError, exceptions.ComposeError, exceptions.TransactionError, exceptions.BalanceError) as error:
                    error_msg = str(error.__class__.__name__) + ': ' + str(error)
                    return flask.Response(error_msg, 400, mimetype='application/json')                        
            else:
                # Need to de-generate extra_args to pass it through.
                query_args = dict([item for item in extra_args])
                operator = query_args.pop('op', 'AND')
                # Put the data into specific dictionary format.
                data_filter = [{'field': key, 'op': '==', 'value': value} for (key, value) in query_args.items()]

                # Run the query.
                try:
                    query_data = get_rows(db, table=query_type, filters=data_filter, filterop=operator)
                except APIError as error:
                    return flask.Response(str(error), 400, mimetype='application/json')

            # See which encoding to choose from.
            file_format = flask_request.headers['Accept']
            # JSON as default.
            if file_format == 'application/json' or file_format == '*/*':
                response_data = json.dumps(query_data)
            elif file_format == 'application/xml':
                # Add document root for XML. Note when xmltodict encounters a list, it produces separate tags for every item.
                # Hence we end up with multiple query_type roots. To combat this we put it in a separate item dict.
                response_data = serialize_to_xml({query_type: {'item': query_data}})
            else:
                error = 'Invalid file format: "%s".' % file_format
                return flask.Response(error, 400, mimetype='application/json')

            response = flask.Response(response_data, 200, mimetype=file_format)
            return response
예제 #2
0
        def handle_rest(path_args, flask_request):
            """Handle /REST/ route. Query the database using get_rows or create transaction using compose_transaction."""
            url_action = flask_request.path.split('/')[-1]
            if url_action == 'compose':
                compose = True
            elif url_action == 'get':
                compose = False
            else:
                error = 'Invalid action "%s".' % url_action
                return flask.Response(error, 400, mimetype='application/json')

            # Get all arguments passed via URL.
            url_args = path_args.split('/')
            try:
                query_type = url_args.pop(0).lower()
            except IndexError:
                error = 'No query_type provided.'
                return flask.Response(error, 400, mimetype='application/json')
            # Check if message type or table name are valid.
            if (compose and query_type not in API_TRANSACTIONS) or \
               (not compose and query_type not in API_TABLES):
                error = 'No such query type in supported queries: "%s".' % query_type
                return flask.Response(error, 400, mimetype='application/json')

            # Parse the additional arguments.
            extra_args = flask_request.args.items()
            query_data = {}

            if compose:
                common_args = {}
                transaction_args = {}
                for (key, value) in extra_args:
                    # Determine value type.
                    try:
                        value = int(value)
                    except ValueError:
                        try:
                            value = float(value)
                        except ValueError:
                            pass
                    # Split keys into common and transaction-specific arguments. Discard the privkey.
                    if key in COMMONS_ARGS:
                        common_args[key] = value
                    elif key == 'privkey':
                        pass
                    else:
                        transaction_args[key] = value

                # Must have some additional transaction arguments.
                if not len(transaction_args):
                    error = 'No transaction arguments provided.'
                    return flask.Response(error,
                                          400,
                                          mimetype='application/json')

                # Compose the transaction.
                try:
                    query_data = compose_transaction(self.db,
                                                     name=query_type,
                                                     params=transaction_args,
                                                     **common_args)
                except (script.AddressError, exceptions.ComposeError,
                        exceptions.TransactionError,
                        exceptions.BalanceError) as error:
                    error_msg = logging.warning(
                        "{} -- error composing {} transaction via API: {}".
                        format(str(error.__class__.__name__), query_type,
                               str(error)))
                    return flask.Response(error_msg,
                                          400,
                                          mimetype='application/json')
            else:
                # Need to de-generate extra_args to pass it through.
                query_args = dict([item for item in extra_args])
                operator = query_args.pop('op', 'AND')
                # Put the data into specific dictionary format.
                data_filter = [{
                    'field': key,
                    'op': '==',
                    'value': value
                } for (key, value) in query_args.items()]

                # Run the query.
                try:
                    query_data = get_rows(self.db,
                                          table=query_type,
                                          filters=data_filter,
                                          filterop=operator)
                except APIError as error:
                    return flask.Response(str(error),
                                          400,
                                          mimetype='application/json')

            # See which encoding to choose from.
            file_format = flask_request.headers['Accept']
            # JSON as default.
            if file_format == 'application/json' or file_format == '*/*':
                response_data = json.dumps(query_data)
            elif file_format == 'application/xml':
                # Add document root for XML. Note when xmltodict encounters a list, it produces separate tags for every item.
                # Hence we end up with multiple query_type roots. To combat this we put it in a separate item dict.
                response_data = serialize_to_xml(
                    {query_type: {
                        'item': query_data
                    }})
            else:
                error = 'Invalid file format: "%s".' % file_format
                return flask.Response(error, 400, mimetype='application/json')

            response = flask.Response(response_data, 200, mimetype=file_format)
            return response