Add http server jsonrpc code
This commit is contained in:
parent
a7f859b952
commit
2e687114af
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
dist/
|
||||||
|
*.egg-info
|
||||||
|
gmon.out
|
3
config/httpd.ini
Normal file
3
config/httpd.ini
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[httpd]
|
||||||
|
host =
|
||||||
|
port =
|
2
config/store.ini
Normal file
2
config/store.ini
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[store]
|
||||||
|
base_dir = /run
|
144
eth_stat_syncer/runnable/server.py
Normal file
144
eth_stat_syncer/runnable/server.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# standard import
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
from http.server import (
|
||||||
|
HTTPServer,
|
||||||
|
BaseHTTPRequestHandler,
|
||||||
|
)
|
||||||
|
|
||||||
|
# external imports
|
||||||
|
import confini
|
||||||
|
from jsonrpc_std.parse import jsonrpc_from_str
|
||||||
|
from jsonrpc_std.interface import jsonrpc_response
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
from eth_stat_syncer.store import RunStore
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.WARNING)
|
||||||
|
logg = logging.getLogger()
|
||||||
|
|
||||||
|
default_config_dir = os.environ.get('CONFINI_DIR', './config')
|
||||||
|
|
||||||
|
argparser = argparse.ArgumentParser()
|
||||||
|
argparser.add_argument('-c', '--config', dest='c', default=default_config_dir, type=str, help='rpc provider')
|
||||||
|
argparser.add_argument('--host', type=str, help='httpd host')
|
||||||
|
argparser.add_argument('--port', type=str, help='httpd port')
|
||||||
|
argparser.add_argument('--store-dir', dest='store_dir', type=str, help='syncerd data store base directory')
|
||||||
|
argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration')
|
||||||
|
argparser.add_argument('-v', action='store_true', help='be verbose')
|
||||||
|
argparser.add_argument('-vv', action='store_true', help='be more verbose')
|
||||||
|
args = argparser.parse_args()
|
||||||
|
|
||||||
|
if args.vv:
|
||||||
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
elif args.v:
|
||||||
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
|
|
||||||
|
config = confini.Config(args.c, args.env_prefix)
|
||||||
|
config.process()
|
||||||
|
# override args
|
||||||
|
args_override = {
|
||||||
|
'HTTPD_HOST': getattr(args, 'host'),
|
||||||
|
'HTTPD_PORT': getattr(args, 'port'),
|
||||||
|
'STORE_BASE_DIR': getattr(args, 'store_dir'),
|
||||||
|
}
|
||||||
|
config.dict_override(args_override, 'cli flag')
|
||||||
|
logg.debug('loaded config: {}\n'.format(config))
|
||||||
|
|
||||||
|
class StatRequestHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
|
runstore = None
|
||||||
|
server_version = 'eth_stat_syncer/0.0.1'
|
||||||
|
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
|
||||||
|
if self.headers.get('Content-Type') != 'application/json':
|
||||||
|
self.send_response(400, 'me read json only')
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
|
|
||||||
|
if 'application/json' not in self.headers.get('Accept').split(','):
|
||||||
|
self.send_response(400, 'me json only speak')
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
|
|
||||||
|
l = self.headers.get('Content-Length')
|
||||||
|
try:
|
||||||
|
l = int(l)
|
||||||
|
except ValueError:
|
||||||
|
self.send_response(400, 'content length must be integer')
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
|
if l > 4096:
|
||||||
|
self.send_response(400, 'too much information')
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
|
if l < 0:
|
||||||
|
self.send_response(400, 'you are too negative')
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
|
|
||||||
|
b = b''
|
||||||
|
c = 0
|
||||||
|
while c < l:
|
||||||
|
d = self.rfile.read(l-c)
|
||||||
|
if d == None:
|
||||||
|
break
|
||||||
|
b += d
|
||||||
|
c += len(d)
|
||||||
|
if c > 4096:
|
||||||
|
self.send_response(413, 'i should slap you around for lying about your size')
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
|
|
||||||
|
o = None
|
||||||
|
err = None
|
||||||
|
try:
|
||||||
|
o = jsonrpc_from_str(b.decode('utf-8'))
|
||||||
|
except JSONRPCException as e:
|
||||||
|
err = e
|
||||||
|
|
||||||
|
if err != None:
|
||||||
|
res = e
|
||||||
|
self.send_response(200, 'alas with jsonrpc error')
|
||||||
|
|
||||||
|
else:
|
||||||
|
r = self.runstore.get('high', 'minute')
|
||||||
|
r = int(r)
|
||||||
|
if r == 0:
|
||||||
|
r = 1
|
||||||
|
res = jsonrpc_response(o['id'], r)
|
||||||
|
logg.debug('returning {} for req {} {}'.format(r, o, self.requestline))
|
||||||
|
self.send_response(200, 'It\'s a gas')
|
||||||
|
|
||||||
|
b = json.dumps(res).encode('utf-8')
|
||||||
|
l = len(b)
|
||||||
|
self.send_header('Content-Length', str(l))
|
||||||
|
self.send_header('Cache-Control', 'no-cache')
|
||||||
|
self.send_header('Content-Type', 'application/json')
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
c = 0
|
||||||
|
while c < l:
|
||||||
|
n = self.wfile.write(b[c:])
|
||||||
|
c += n
|
||||||
|
|
||||||
|
|
||||||
|
def run(store, host=None, port=None):
|
||||||
|
if host == None:
|
||||||
|
host = ''
|
||||||
|
if port == None:
|
||||||
|
port = 8000
|
||||||
|
StatRequestHandler.runstore = store
|
||||||
|
server_address = (host, port)
|
||||||
|
httpd = HTTPServer(server_address, StatRequestHandler)
|
||||||
|
httpd.serve_forever()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
store = RunStore(basedir=config.get('STORE_BASE_DIR'))
|
||||||
|
run(store, host=config.get('HTTPD_HOST'), port=config.get('HTTPD_PORT'))
|
@ -91,7 +91,6 @@ def main():
|
|||||||
syncer.loop(0.0, conn)
|
syncer.loop(0.0, conn)
|
||||||
except NoBlockForYou:
|
except NoBlockForYou:
|
||||||
logg.info('history done at {}'.format(syncer.backend.get()))
|
logg.info('history done at {}'.format(syncer.backend.get()))
|
||||||
pass
|
|
||||||
|
|
||||||
syncer_backend = MemBackend(chain_spec, None)
|
syncer_backend = MemBackend(chain_spec, None)
|
||||||
syncer_backend.set(start_block + 1, 0)
|
syncer_backend.set(start_block + 1, 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user