from sanic.response import text from sanic.server import serve app = Sanic() @app.route("/sync") async def get_sync(request): if 'before' in request.args: await asyncio.sleep(float(request.args.get('before'))) time.sleep(float(request.args.get('sleep', 5))) if 'after' in request.args: await asyncio.sleep(float(request.args.get('after'))) return text('OK') @app.route("/async") async def get_async(request): await asyncio.sleep(5) return text('OK') loop = asyncio.get_event_loop() server_settings = app._helper(host="0.0.0.0", port=5000, access_log=False, loop=loop, run_async=True) loop.run_until_complete(serve(**server_settings)) try: loop.run_forever() finally: loop.close()
class RPCServer: def __init__(self, ethpconnect='127.0.0.1', ethpport=9500, rpcconnect='127.0.0.1', rpcport=8545, ipcconnect=None, blocknotify=None, walletnotify=None, alertnotify=None, tls=False, *, loop=None): self._loop = loop or asyncio.get_event_loop() self._app = Sanic(__name__, log_config=None, error_handler=SentryErrorHandler()) self._host = ethpconnect self._port = ethpport self._rpc_host = rpcconnect self._rpc_port = rpcport self._unix_socket = ipcconnect self._blocknotify = blocknotify self._walletnotify = walletnotify self._alertnotify = alertnotify self._tls = tls self._log = logging.getLogger('rpc_server') self.routes() @property def endpoint(self): schema = 'http' if self._tls: schema += 's' return ('{0}://{1}:{2}'.format(schema, self._rpc_host, self._rpc_port) if not self._unix_socket else 'unix://{0}'.format( self._unix_socket)) @property def cmds(self): cmds = {} if self._blocknotify: cmds['blocknotify'] = self._blocknotify if self._walletnotify: cmds['walletnotify'] = self._walletnotify if self._alertnotify: cmds['alertnotify'] = self._alertnotify return cmds def before_server_start(self): @self._app.listener('before_server_start') async def initialize_scheduler(app, loop): self._proxy = await create_ethereumd_proxy(self.endpoint, loop=loop) self._poller = Poller(self._proxy, self.cmds, loop=loop) self._scheduler = AsyncIOScheduler({'event_loop': loop}) if self._poller.has_blocknotify: self._scheduler.add_job(self._poller.blocknotify, 'interval', id='blocknotify', seconds=1) if self._poller.has_walletnotify: self._scheduler.add_job(self._poller.walletnotify, 'interval', id='walletnotify', seconds=1) if self._scheduler.get_jobs(): self._scheduler.start() return initialize_scheduler def routes(self): self._app.add_route(self.handler_index, '/', methods=['POST']) self._app.add_route(self.handler_log, '/_log/', methods=['GET', 'POST']) async def handler_index(self, request): data = request.json try: id_, method, params, _ = data['id'], \ data['method'], data['params'], data['jsonrpc'] except KeyError: return response.json({ 'id': data.get('id', 0), 'result': None, 'error': { 'message': 'Invalid rpc 2.0 structure', 'code': -32602 } }) try: result = (await getattr(self._proxy, method)(*params)) except AttributeError as e: self._log.exception(e) return response.json({ 'id': id_, 'result': None, 'error': { 'message': 'Method not found', 'code': -32601 } }) except TypeError as e: self._log.exception(e) return response.json({ 'id': id_, 'result': None, 'error': { 'message': e.args[0], 'code': -1 } }) except BadResponseError as e: return response.json({ 'id': id_, 'result': None, 'error': { 'message': e.msg, 'code': e.code } }) else: return response.json({'id': id_, 'result': result, 'error': None}) async def handler_log(self, request): self._log.warning('\nRequest args: %s;\nRequest body: %s', request.args, request.body) return response.json({'status': 'OK'}) def serve(self): self.before_server_start() self._log.info(GREETING) server_settings = self._app._helper(host=self._host, port=self._port, debug=True, loop=self._loop, backlog=100, run_async=True, has_log=False) return serve(**server_settings) def run(self): self._loop.run_until_complete(self.serve()) try: self._log.warning('Starting server on http://%s:%s/...', self._host, self._port) self._loop.run_forever() except Exception: self._log.warning('Stoping server...') self._poller.stop()