nanorpc: magic library for a JSON-RPC 2.0 subset (WIP)
Motivation
Typically, writing a client-server networked API (say, a REST API) involves the following three steps:
- Specify the protocol, in English
- Implement the server side of the protocol
- Separately implement the client side of the protocol
This is annoying and error-prone. The protocol is essentially specified three times in three different places and ways, and keeping them in sync is a huge chore.
Instead, we want to specify the protocol once, then automatically have:
- A server implementation, generic over
- The business logic of every endpoint
- The low-level network details (e.g. "listen at this HTTP endpoint")
- A client implementation, generic over the low-level network details (e.g. "call this HTTP endpoint)
- Rust's type system fully utilized to help avoid bugs from things like serialization and deserialization mismatch, typos, etc.
About nanorpc
nanorpc does exactly. It is a JSON-RPC subset implementation with a macro, #[nanorpc_derive], that given a trait representing the API interface, abstracts away all the duplicate parts of implementing an API.
In particular:
nanorpcdefines dynamically typed JSON-RPC server and client traits:- a trait
RpcServicethat describes a JSON-RPC server-side responder (given a JSON request, produce a JSON response) - a trait
RpcTransportthat describes a JSON-RPC client-side requester (given a JSON request, talk to somebody else to produce a JSON response)
- a trait
[nanorpc_derive], given a traitFooProtocolthat describes the RPC methods, their argument types, and their return types, derives:- a struct
FooServicethat, given any "business logic" struct that implementsFooProtocol, wraps it into something implementingRpcService - a struct
FooClientthat, given any JSON transport implemetningRpcTransport, wraps it into a struct with methods corresponding to the RPC methods.
- a struct
For example:
// Autogenerates a server struct:
;
// Autogenerates a client struct like:
;
At the JSON level, the above protocol will respond to a JSON-RPC 2.0 request like:
{"jsonrpc": "2.0", "method": "mult", "params": [42, 23], "id": 1}
with
{"jsonrpc": "2.0", "result": 966, "id": 1}