Skip to main content

Async JSON-RPC 2.0 protocol + server powered by asyncio

Project description

Async JSON-RPC 2.0 protocol + asyncio server

Python package status security status

Lightweight JSON-RPC 2.0 protocol implementation and asynchronous server powered by asyncio. This library is a successor of json-rpc and written by the same team.

Features:

  • Full JSON-RPC 2.0 Implementation.
  • Async request manager that handles the protocol.
  • Vanilla Python, no dependencies.
  • API server setup in 1 min.
  • Same development team as json-rpc, largely compatible code.

Installing

$ pip install ajsonrpc

Quick Start

This package contains core JSON-RPC 2.0 primitives (request, response, etc.) and convenient backend-independent abstractions on top of them: dispatcher and request manager. These modules mirror implementation in the original json-rpc package with minor changes and improvements. Below is a summary of each module.

Core Module

Consists of JSON-RPC 2.0 primitives: request, batch request, response, batch response, error. It also defines base classes for custom errors and exceptions.

Development principles:

  • If python object is created or modified without exceptions, it contains valid data.
  • Private state <object>._body contains the single source of truth. It is accessible and modifiable via getters (properties) and setters that ensure validation.
  • body is always a dictionary with primitive keys and values (the only exception is response.result that could hold any value defined by the application).
  • Constructor, getters and setters operate with JSON-RPC defined types, e.g. response.error always has JSONRPC20Error type. Most of other types are strings and numbers.

Unlike json-rpc package, core module does not deal with serialization/de-serialization, this logic was moved to manager.

Dispatcher

Dispatcher is a dict-like object that maps method names to executables. One can think of it as an inproved dictionary, in fact it is inherited from MutableMapping. Some of the ways to add methods to dispatcher:

# init
d = Dispatcher({"sum": lambda a, b: a + b})

# set item
d["max"] = lambda a, b: max(a, b)

# function decorator
@d.add_method
def add(x, y):
    return x + y

# Add class or object
class Math:
    def sum(self, a, b):
        return a + b

    def diff(self, a, b):
        return a - b

d.add_class(Math)
d.add_object(Math())
d.add_dict({"min": lambda a, b: min(a, b)})

# rename function
d.add_method(add, name="my_add")

# prefix methos
d.add_class(Math, prefix="get_")

Manager

Manager generates a response for a request. It handles common routines: request parsing, exception handling and error generation, parallel request execution for batch requests, serialization/de-serialization. Manager is asynchronous and dackend agnostic, it exposes following common methods:

# Get a response object for a single request. Used by other methods.
async def get_response_for_request(
    self, request: JSONRPC20Request
    ) -> Optional[JSONRPC20Response]

# Get (batch) response for a string payload. Handles de-serialization and parse errors.
async def get_response_for_payload(
    self, payload: str
    ) -> Optional[Union[JSONRPC20Response, JSONRPC20BatchResponse]]

# Most high-level method, returns string json for a string payload.
async def get_payload_for_payload(self, payload: str) -> str

Vanilla Server (Demo)

This package comes with an asyncio Protocol-based minimalistic server script async-json-rpc-server. One could think of it as a bottle-py of API servers.

This was an experiment turned prototype: unlike json-rpc that requires some "shell" like Django or Flask to work, this package relies on asyncio and therefore could build on top of its TCP server. Indeed, JSON-RPC 2.0 is intentionally simple: server does not require views, has only one endpoint (routing is not required), only deals with json. Hence, vanilla code would be not only sufficient but likely faster than any framework.

This idea of self-sufficient server was extended further: what would be the minimum interface that allows to plug application code? What if zero integration is required? Likely, this was possible with runtime method introspection: async-json-rpc-server parses given file with methods and exposes all of them. Let's consider an example:

# examples/methods.py
import asyncio

def echo(s='pong'):
    return s

def mul2(a, b):
    return a * b

async def say_after(delay, what):
    await asyncio.sleep(delay)
    return what

To launch a server based on above methods, simply run:

$ async-json-rpc-server examples/methods.py --port=8888

(Ctrl+C stops the server).

Single request example:

$ curl -H 'Content-Type: application/json' \
    -d '{"jsonrpc": "2.0", "method": "echo", "id": 0}' \
    http://127.0.0.1:8888

{"jsonrpc": "2.0", "id": 0, "result": "pong"}

Batch request example: server-example-batch

Backends

This package does not have backend support for frameworks yet (unlike json-rpc that support Django and Flask). If you need to support any framework, please open an issue with your request.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ajsonrpc-1.0.0a0.tar.gz (20.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ajsonrpc-1.0.0a0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file ajsonrpc-1.0.0a0.tar.gz.

File metadata

  • Download URL: ajsonrpc-1.0.0a0.tar.gz
  • Upload date:
  • Size: 20.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.1

File hashes

Hashes for ajsonrpc-1.0.0a0.tar.gz
Algorithm Hash digest
SHA256 6b5e7124a67441a060f2f6bfa3350eb26eb698bbdc219a31e1131cf8fdb57c19
MD5 ccd8e6b0dc6b50b67314da18d0c140fe
BLAKE2b-256 984d3b48b6d9a62befc5973c11347d28beea70e260c9b28fabcbad41a2e6515f

See more details on using hashes here.

File details

Details for the file ajsonrpc-1.0.0a0-py3-none-any.whl.

File metadata

  • Download URL: ajsonrpc-1.0.0a0-py3-none-any.whl
  • Upload date:
  • Size: 19.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.1

File hashes

Hashes for ajsonrpc-1.0.0a0-py3-none-any.whl
Algorithm Hash digest
SHA256 3baab7a09fced3b41b57d4c7b597c267bba9c0899f32a9fff83e36f913461ab7
MD5 718ac3ede283b8c6252daa4b7733a1b4
BLAKE2b-256 8ebe9265059f294d02168feacb6e59ee15fa3bd554cd1ae7ee59fc651d27bf15

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page