Pure Fantom implementation of JSON-RPC 2.0 protocol
Fantom
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
examples
jsonrpc
.gitignore
README.org

README.org

What

Pure Fantom implementation of client and server conforming JSON-RPC 2.0 protocol. Two reference implementations are planned to make sure the core is flexible enough:

  • HTTP-based. Server is a WebMod, client sends POST requests using WebClient.
  • TCP-based. Client connects to socket and sends requests. Server processes them asynchronously and returns results once it is done.

Why?

Description

Here are the core classes used on server side:

  • Server – transport-agnostic call translator which returns Str request from Str response. All calls are delegated to a Handler. Library users are very unlikely require to change it.
  • Handler – abstract method executor
  • ReflectHandler – handler implementation which uses reflection to call methods of current object. Also gives an access to fields as methods without params.

There are two ready-to-use components which enable remote access to server:

  • RpcMod – accepts JSON requests from HTTP POSTs and writes back JSON responses
  • RpcTcpService – binds to TCP socket and asynchronously processes incoming messages by invoking InStream#.readUtf

Client side has two implementations of clients – sync and async. Sync client blocks until it gets a response, and async client receives callback along with request which will be invoked once response is received. To add custom implementation, it is required to implement either SyncTransport or AsyncTransport and then just create corresponding client by invoking Client.sync(transport) or Client.async(transport). Two ready-to-use client implementations available:

  • RpcWebClient – sync transport which sends POST requests with JSON to given URI
  • RpcTcpClient – async transport which writes JSON requests as UTF strings

Examples

Web

Simple server which exposes a sum method:

using util
using jsonrpc

class Server : AbstractMain
{
  @Opt Int port := 8080

  override Int run()
  {
    runServices([
        WispService
        {
          it.port = this.port
          it.root = RpcMod(MathHandler())
        }
       ])
  }
}

const class MathHandler : ReflectHandler
{
  Int sum(Int[] args) { args.reduce(0) |Int r, Int v->Int| { r + v } }
}

Corresponding client:

echo(RpcWebClient(`http://localhost:8080`).request("sum", [[1,2,3]]) 
//output: 6

Inet

Server:

using util
using jsonrpc

class Server : AbstractMain
{
  @Opt Int port := 4750

  override Int run() { runServices([RpcService(MathHandler(), port)]) }
}

const class MathHandler : ReflectHandler
{
  Int sum(Int[] args) { args.reduce(0) |Int r, Int v->Int| { r + v } }
}

Client:

//Callback accepts a Func as a parameter, so that invocation of this func 
//will throw RpcErr in case of error on server side
RpcTcpClient(IpAddr.local, 4750).request("sum", [[1,2,3]]) |res| { echo(res.call) }