Skip to content
This repository has been archived by the owner on Nov 21, 2023. It is now read-only.
Zeng Ke edited this page May 27, 2022 · 8 revisions

jlib

jlib is a JSONRPC 2.0 library and a suite of client utilities in golang

Install and build

% git checkout https://github.com/superisaac/jlib
% cd jlib
% make test # run unit test
...
% make build  # build cli tools
go build -gcflags=-G=3 -o bin/jsonrpc-call cli/call/jsonrpc_call.go
go build -gcflags=-G=3 -o bin/jsonrpc-notify cli/notify/jsonrpc_notify.go
go build -gcflags=-G=3 -o bin/jsonrpc-watch cli/watch/jsonrpc_watch.go
go build -gcflags=-G=3 -o bin/jlib-example-fifo examples/fifo/main.go

Examples

Start a simple JSONRPC server

server side code

import (
    // "github.com/superisaac/jlib"
    "github.com/superisaac/jlib/http"
)
// create a HTTP/1 handler, currently http1, http2 and websocket handlers are supported
server := jlibhttp.NewH1Handler(nil)

// register an actor function
server.Actor.OnTyped("echo", func(text string) (string, error) {
    return "echo " + text, nil
})
// serve the JSONRPC at port 8000
jlibhttp.ListenAndServe(rootCtx, ":8000", server)

the server can be tested using client tools jsonrpc-call

% bin/jsonrpc-call -c http://127.0.0.1:8000 echo hi
{
   "jsonrpc": "2.0",
   "id": "1",
   "result": "echo hi"
}

Initialize a JSONRPC request

import (
    "context"
    "github.com/superisaac/jlib"
    "github.com/superisaac/jlib/http"
)

// create a jsonrpc client according to the server url
// the supported url schemes are: http, https, h2, h2c, ws and wss
client := jlibhttp.NewClient("http://127.0.0.1:8000")

// create a request message with a random id field
reqmsg := jlib.NewRequestMessage(jlib.NewUuid(), "echo", []interface{}{"hi5"})
fmt.Printf("request message: %s\n", jlib.MessageString(reqmsg))

resmsg, err := client.Call(context.Background(), reqmsg)
fmt.Printf("result message: %s\n", jlib.MessageString(resmsg))
assert.True(resmsg.IsResultOrError())  // resmsg is a Result type message or an Error type message
assert.Equal("echo hi5", resmsg.MustResult())

// a notify message, notify message doesn't have id field and doesn't expect result
ntfmsg := jlib.NewNotifyMessage("echo", []interface{}{"hi6"})
err := client.Send(context.Background(), ntfmsg)

FIFO service

the FIFO service is an example that demonstrates how jlib server and client works together without writing any code. the server maintains an array in memory, you can push/pop/get items from it and list all items, you can even subscribe the item additions using streaming connections.

Start server which listens at port 6000

% bin/jlib-example-fifo
INFO[0000] Example fifo service starts at 127.0.0.1:6000

Open another terminal and type a sequence of commands

# list the fifo and get an empty list
% bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_list
{
  "jsonrpc": "2.0",
  "id": "a85bfe31c94f4a5bb0fcb6539bbd6d66",
  "result": []
}

# push an item "hello"
 % bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_push hello
{
  "jsonrpc": "2.0",
  "id": "c460ebe3a9094249a043b6cddf3fa29f",
  "result": "ok"
}

# call list again, now that the item "hello" is in 
% bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_list
{
  "jsonrpc": "2.0",
  "id": "b3262cc3166e45e2bb5e58939d5e73bb",
  "result": [
    "hello"
  ]
}

# push another item 5(integer)
% bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_push 5
{
  "jsonrpc": "2.0",
  "id": "dc2bbac79e6841d78786e5ff5fc37c13",
  "result": "ok"
}

# now there are 2 items
% bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_list
{
  "jsonrpc": "2.0",
  "id": "29ca7b80ac504e9c9dd3513f3d4b966d",
  "result": [
    "hello",
    5
  ]
}

# get fifo[1], which is the second item
% bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_get 1
{
  "jsonrpc": "2.0",
  "id": "1c3fd5fe30034b72b115705263961c22",
  "result": 5
}

# pop an item out of the fifo
% bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_pop
{
  "jsonrpc": "2.0",
  "id": "df4bbe13c79c4fdc914ed8961ced9cf3",
  "result": "ok"
}

# the item 5 is out
% bin/jsonrpc-call -c http://127.0.0.1:6000 fifo_list
{
  "jsonrpc": "2.0",
  "id": "f767a5275f544b9db2ba091cdebd9f5f",
  "result": [
    "hello"
  ]
}

Open another terminal to subscribe item addition

# jsonrpc-watch connect to server, send the initial request message and wait data from server.
% bin/jsonrpc-watch -c h2c://127.0.0.1:6000 fifo_subscribe
{
  "jsonrpc": "2.0",
  "id": "abdc63d3873649a1a7a2b1bd49916e44",
  "result": "ok"
}

Note that the cli command is bin/jsonrpc-watch instead of bin/jsonrpc-call and the server url scheme h2c:// which means the client can be in streaming mode, ws:// is another streaming schema but the http/1 client doesn't support streaming.

Now switch to the second terminal and push another item, it is appeared immediately in the subscription terminal.

 % bin/jsonrpc-watch -c h2c://127.0.0.1:6000 fifo_subscribe
{
  "jsonrpc": "2.0",
  "id": "abdc63d3873649a1a7a2b1bd49916e44",
  "result": "ok"
}
{
  "jsonrpc": "2.0",
  "method": "fifo_subscription",
  "params": [
    "world"
  ]
}