jsonrpcserver

jsonrpcserver Guide

Jsonrpcserver allows you to act on remote procedure calls.

Installation

Install the package with pip:

pip install jsonrpcserver

For Python versions older than 3.6, install a 3.x version, and jump over to the 3.x docs.

pip install "jsonrpcserver>=3,<4"

There are three public functions, method, serve and dispatch.

Methods

Use the @method decorator to register functions that can be called remotely:

from jsonrpcserver import method, dispatch, serve

@method
def ping():
    return 'pong'

Methods can accept either positional or named arguments (but not both – this is a limitation of JSON-RPC).

The RPC method will have the same name as the Python function; to use a different name, pass it to the decorator, for example @method(name="foo").

Serve

Start the development server:

>>> serve()
 * Listening on port 5000

For production, use a more sophisticated framework (see examples in various frameworks). For those, there’s a dispatch function.

Dispatch

The dispatch function processes a JSON-RPC request and calls the appropriate method:

response = dispatch('{"jsonrpc": "2.0", "method": "ping", "id": 1}')

The return value is a Response object.

Use str() to get the JSON-serialized response:

>>> str(response)
'{"jsonrpc": "2.0", "result": "pong", "id": 1}'

deserialized() gives the response as a Python object:

>>> response.deserialized()
{'jsonrpc': '2.0', 'result': 'pong', 'id': 1}

There’s also an HTTP status code if needed:

>>> response.http_status
200

To use a custom serializer or deserializer, pass them to dispatch:

response = dispatch(request, serialize=ujson.dumps, deserialize=ujson.loads)

Context

If you need to pass some extra data to the methods, such as configuration settings, or the request object from the server framework, pass a context object:

dispatch(request, context={'feature_enabled': True})

The methods will receive this as the first positional param:

@method
def ping(context):
    ...

Configuration

Other options can be passed to dispatch, or put in a config file (see below):

basic_logging

Adds log handlers, to log all requests and responses to stderr.

convert_camel_case

Attempts to clean up requests before processing, by changing the method and parameter names to snake case. Default is False.

debug

If True, more information is included in error responses, such as an exception message. For ApiError, this value is ignored. Default is False.

trim_log_values

Show abbreviated requests and responses in logs. Default is False.

Config file

Here’s an example of the config file .jsonrpcclientrc - this should be placed in the current or home directory:

[general]
basic_logging = yes
convert_camel_case = yes
debug = yes
trim_log_values = yes

Errors

The library handles most errors related to the JSON-RPC standard.

from jsonrpcserver.exceptions import InvalidParamsError

@method
def fruits(color):
    if color not in ("red", "orange", "yellow"):
        raise InvalidParamsError("No fruits of that colour")

The dispatcher will give the appropriate response:

>>> str(dispatch('{"jsonrpc": "2.0", "method": "fruits", "params": {"color": "blue"}, "id": 1}'))
'{"jsonrpc": "2.0", "error": {"code": -32602, "message": "Invalid parameters"}, "id": 1}'

To send some other application-defined error response, raise an ApiError in a similar way.

from jsonrpcserver.exceptions import ApiError

@method
def my_method():
    if some_condition:
        raise ApiError("Can't fulfill the request")

To include the message passed when raising the exception, set debug to True. (See Configuration above.)

Async

Asyncio is supported, allowing requests to be dispatched to coroutines.

from jsonrpcserver import method, async_dispatch

@method
async def ping():
    return await some_long_running_task()

response = await async_dispatch(request)

Questions? beauinmelbourne@gmail.com or create an issue.