2021-04-09 17:39:00 +02:00
# 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 ' )
2022-03-08 11:17:01 +01:00
argparser . add_argument ( ' --port ' , type = int , help = ' httpd port ' )
2021-04-09 17:39:00 +02:00
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
2022-03-08 11:17:01 +01:00
accept = [ ' application/json ' ]
try :
accept = self . headers . get ( ' Accept ' ) . split ( ' , ' )
except AttributeError :
pass
logg . debug ( ' accept is {} ' . format ( accept ) )
nocomprendo = True
if ' */* ' in accept :
nocomprendo = False
elif ' application/json ' in accept :
nocomprendo = False
elif ' * ' in accept :
nocomprendo = False
if nocomprendo :
2021-04-09 17:39:00 +02:00
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 ' ) )