pop required params

This commit is contained in:
William Luke 2021-11-19 16:50:13 +03:00
parent b42f076d85
commit 6a0544b579
5 changed files with 65 additions and 44 deletions

View File

@ -1,39 +1,30 @@
# standard imports # standard imports
import json import json
import logging import logging
import os
import sys
import uuid
from os import path from os import path
from urllib.parse import parse_qsl, urlparse from urllib.parse import parse_qsl, urlparse
import redis from cic_eth.server.celery_helper import call
from cic_eth.api.api_task import Api
from cic_eth.server.UWSGIOpenAPIRequest import UWSGIOpenAPIRequest from cic_eth.server.UWSGIOpenAPIRequest import UWSGIOpenAPIRequest
from openapi_core import create_spec from openapi_core import create_spec
from openapi_core.validation.request.datatypes import OpenAPIRequest from openapi_core.validation.request.datatypes import OpenAPIRequest
from openapi_core.validation.request.validators import RequestValidator from openapi_core.validation.request.validators import RequestValidator
from openapi_spec_validator.schemas import read_yaml_file from openapi_spec_validator.schemas import read_yaml_file
from werkzeug.wrappers import Request
from cic_eth.server.celery_helper import call
spec_dict = read_yaml_file(path.join(path.dirname( spec_dict = read_yaml_file(path.join(path.dirname(
__file__), '../../server/openapi/server.yaml')) __file__), '../../server/openapi/server.yaml'))
spec = create_spec(spec_dict) spec = create_spec(spec_dict)
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() log = logging.getLogger()
# uwsgi application # uwsgi application
def application(env, start_response): def application(env, start_response):
print(spec) oAPIRequest = UWSGIOpenAPIRequest(env)
request = Request(env)
oAPIRequest = UWSGIOpenAPIRequest(request)
validator = RequestValidator(spec) validator = RequestValidator(spec)
result = validator.validate(oAPIRequest) result = validator.validate(oAPIRequest)
@ -51,31 +42,62 @@ def application(env, start_response):
return [content] return [content]
parsed_url = urlparse(env.get('REQUEST_URI')) # /api parsed_url = urlparse(env.get('REQUEST_URI')) # /api
path = parsed_url.path path = parsed_url.path
parsed_url.params
params = dict(parse_qsl(parsed_url.query)) params = dict(parse_qsl(parsed_url.query))
# Setup Channel to receive the result
if path == '/list': if path == '/list':
address = params.get('address') address = params.pop('address')
print('address', address) print('address', address, )
# address, limit=10, external_task=None, external_queue=None # address, limit=10
data = call('list', address) data = call('list', address, **params)
elif path == '/balance': elif path == '/balance':
data = call('balance', **params) address = params.pop('address')
token_symbol = params.pop('token_symbol')
data = call('balance', address, token_symbol, **params)
for b in data:
b.update({
"balance_available": int(b['balance_network']) + int(b['balance_incoming']) - int(b['balance_outgoing'])
})
elif path == '/create_account': elif path == '/create_account':
data = call('create_account', **params) data = call('create_account', **params)
elif path == '/refill_gas':
address = params.pop('address')
data = call('refill_gas', address)
elif path == '/ping': elif path == '/ping':
data = call('ping', **params) data = call('ping', **params)
elif path == '/transfer': elif path == '/transfer':
data = call('transfer', **params) from_address = params.pop('from_address')
to_address = params.pop('to_address')
value = params.pop('value')
token_symbol = params.pop('token_symbol')
data = call('transfer', from_address, to_address, value, token_symbol)
elif path == '/transfer_from': elif path == '/transfer_from':
data = call('transfer_from', **params) from_address = params.pop('from_address')
to_address = params.pop('to_address')
value = params.pop('value')
token_symbol = params.pop('token_symbol')
spender_address = params.pop('spender_address')
data = call('transfer_from', from_address, to_address,
value, token_symbol, spender_address)
elif path == '/token': elif path == '/token':
data = call('token', **params) token_symbol = params.pop('token_symbol')
data = call('token', token_symbol, **params)
elif path == '/tokens': elif path == '/tokens':
data = call('tokens', **params) token_symbols = params.pop('token_symbols')
data = call('tokens', token_symbols, **params)
elif path == '/default_token': elif path == '/default_token':
data = call('default_token', ) data = call('default_token', )
json_data = json.dumps(data) json_data = json.dumps(data)
content = json_data.encode('utf-8') content = json_data.encode('utf-8')
headers = [] headers = []

View File

@ -9,19 +9,18 @@ from werkzeug.datastructures import ImmutableMultiDict
from openapi_core.validation.request.datatypes import OpenAPIRequest from openapi_core.validation.request.datatypes import OpenAPIRequest
from openapi_core.validation.request.datatypes import RequestParameters from openapi_core.validation.request.datatypes import RequestParameters
from werkzeug.wrappers import Request
class UWSGIOpenAPIRequestFactory: class UWSGIOpenAPIRequestFactory:
@classmethod @classmethod
def create(cls, request): def create(cls, env):
""" """
Converts a requests request to an OpenAPI one Converts a requests request to an OpenAPI one
Internally converts to a `PreparedRequest` first to parse the exact
payload being sent
""" """
if isinstance(request, Request): request = Request(env)
request = request.prepare()
# Method # Method
method = request.method.lower() method = request.method.lower()
@ -44,7 +43,6 @@ class UWSGIOpenAPIRequestFactory:
header = Headers(dict(request.headers)) header = Headers(dict(request.headers))
# Body # Body
# TODO: figure out if request._body_position is relevant
body = request.get_data() body = request.get_data()
# Path gets deduced by path finder against spec # Path gets deduced by path finder against spec

View File

@ -3,28 +3,27 @@ import logging
import sys import sys
import uuid import uuid
import cic_eth.cli
import redis import redis
from cic_eth.api.api_task import Api from cic_eth.api.api_task import Api
from cic_eth.server.config import config from cic_eth.server.config import config
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# TODO Remove
log.setLevel(logging.DEBUG)
celery_app = cic_eth.cli.CeleryApp.from_config(config)
celery_app.set_default()
chain_spec = config.get('CHAIN_SPEC') chain_spec = config.get('CHAIN_SPEC')
celery_queue = config.get('CELERY_QUEUE') celery_queue = config.get('CELERY_QUEUE')
api = Api(
chain_spec,
queue=celery_queue,
)
redis_host = config.get('REDIS_HOST') redis_host = config.get('REDIS_HOST')
redis_port = config.get('REDIS_PORT') redis_port = config.get('REDIS_PORT')
redis_db = config.get('REDIS_DB') redis_db = config.get('REDIS_DB')
def call(method, *args): def call(method, *args, **kwargs):
""" Creates a redis channel and calls `cic_eth.api` with the provided `method` and `*args`. Returns the result of the api call """ Creates a redis channel and calls `cic_eth.api` with the provided `method` and `*args`. Returns the result of the api call
""" """
redis_channel = str(uuid.uuid4()) redis_channel = str(uuid.uuid4())
@ -40,15 +39,16 @@ def call(method, *args):
callback_queue=celery_queue, callback_queue=celery_queue,
) )
getattr(api, method)(*args) getattr(api, method)(*args)
ps.get_message() ps.get_message()
try: try:
o = ps.get_message(timeout=config.get('REDIS_TIMEOUT')) o = ps.get_message(timeout=config.get('REDIS_TIMEOUT'))
except TimeoutError as e: except TimeoutError as e:
sys.stderr.write( sys.stderr.write(
f'cic_eth.api.{method}({args}) timed out:\n {e}') f'cic_eth.api.{method}({args}, {kwargs}) timed out:\n {e}')
sys.exit(1) sys.exit(1)
log.debug(f"cic_eth.api.{method}({args})\n {o}") log.debug(f"cic_eth.api.{method}({args}, {kwargs})\n {o}")
ps.unsubscribe() ps.unsubscribe()
try: try:
@ -59,4 +59,3 @@ def call(method, *args):
sys.stderr.write( sys.stderr.write(
f'Unable to parse Data:\n{o}\n Error:\n{e}') f'Unable to parse Data:\n{o}\n Error:\n{e}')
sys.exit(1) sys.exit(1)

View File

@ -208,6 +208,8 @@ services:
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- cic-eth-tasker - cic-eth-tasker
- cic-eth-tracker
- cic-eth-dispatcher
volumes: volumes:
- signer-data:/run/crypto-dev-signer - signer-data:/run/crypto-dev-signer
- contract-config:/tmp/cic/config/:ro - contract-config:/tmp/cic/config/:ro