tornado plus json

We’ll use Tornado to take JSON-RPC requests. It should respond to “ping” with “pong”.

Install Tornado to take requests and jsonrpcserver to process them:

$ pip install tornado jsonrpcserver

Create a server.py:

from tornado import ioloop, web
from jsonrpcserver.aio import methods
from jsonrpcserver.response import NotificationResponse

@methods.add
async def ping():
    return 'pong'

class MainHandler(web.RequestHandler):
    async def post(self):
        request = self.request.body.decode()
        response = await methods.dispatch(request)
        if not response.is_notification:
            self.write(response)

app = web.Application([(r"/", MainHandler)])

if __name__ == '__main__':
    app.listen(5000)
    ioloop.IOLoop.current().start()

Start the server:

$ python server.py

Synchronous client

Use jsonrpcclient to send requests.

$ pip install 'jsonrpcclient[requests]'
$ python
>>> import jsonrpcclient
>>> jsonrpcclient.request('http://localhost:5000/', 'ping')
--> {"jsonrpc": "2.0", "method": "ping", "id": 1}
<-- {"jsonrpc": "2.0", "result": "pong", "id": 1} (200 OK)
'pong'

Asynchronous client with Tornado

We can send asynchronous requests in Tornado with jsonrpcclient (thanks to saaj):

$ pip install 'jsonrpcclient[tornado]'

Create a client.py:

from tornado import ioloop
from jsonrpcclient.tornado_client import TornadoClient

client = TornadoClient('http://localhost:5000/')

async def main():
    result = await client.request('ping')
    print(result)

ioloop.IOLoop.current().run_sync(main)

The async/await syntax requires Python 3.5+. Prior to that use @gen.coroutine and yield.

$ python client.py
INFO:jsonrpcclient.client.request:{"jsonrpc": "2.0", "method": "ping", "id": 1}
INFO:jsonrpcclient.client.response:{"jsonrpc": "2.0", "result": "pong", "id": 1}
pong