0 branches
Tree Top files
Code
Clone with HTTPS:
56 years ago
..
jsonrpc.v all: super_batch3 fixes last Apr 13 8.49 KB
server_test.v all: more fixes last Apr 19 2.03 KB

JSONRPC

JSON-RPC 2.0 client+server implementation in pure V.

Limitaions

Features

Usage

Request/Response operations

For both Request/Response constructors are provided and must be used for initialization.

import net.jsonrpc

// jsonrpc.new_request(method, params, id)
mut req := jsonrpc.new_request('kv.create', {
    'key':   'key'
    'value': 'value'
}, 'kv.create.1')

println(req.encode())
// '{"jsonrpc":"2.0","method":"kv.create","params":{"key":"key","value":"value"},"id":"kv.create.1"}'

// jsonrpc.new_response(result, error, id)
mut resp := jsonrpc.new_response({
    'key':   'key'
    'value': 'value'
}, jsonrpc.ResponseError{}, 'kv.create.1')

println(resp.encode())
// '{"jsonrpc":"2.0","result":{"key":"key","value":"value"},"id":"kv.create.1"}'

To create a Notification, pass empty string as Request.id (jsonrpc.Empty{}.str() or jsonrpc.empty.str() can be used) (e.g. jsonrpc.new_reponse('method', 'params', jsonrpc.empty.str())). To omit Response.params in encoded json string pass jsonrpc.Empty{} or jsonrpc.empty as value in constructor (e.g. jsonrpc.new_reponse('method', jsonrpc.empty, 'id')). For Response only result or error fields can exist at the same time and not both simultaniously. If error passed to jsonrpc.new_response() the result value will be ignored on Response.encode(). The error field is not generated if jsonrpc.ResponseError{} provided as error into jsonrpc.new_response() (e.g. jsonrpc.new_response("result", jsonrpc.ResponseError{}, "id")). If the empty string passed as Result.id it will use jsonrpc.null as id (translates to json null)

Client

For full usage check client in example

import net
import net.jsonrpc

addr := '127.0.0.1:42228'
mut stream := net.dial_tcp(addr)!
mut c := jsonrpc.new_client(jsonrpc.ClientConfig{
    stream: stream
})

c.notify('kv.create', {
    'key':   'bazz'
    'value': 'barr'
})!

Client can work with any io.ReaderWriter provided into stream field value.

Server

For ready key/value im-memory storage realized with server check this example

import net
import net.jsonrpc

fn handle_test(req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) {
    p := req.decode_params[string]() or {
        wr.write_error(jsonrpc.invalid_params)
        return
    }

    wr.write(p)
}

fn handle_conn(mut conn net.TcpConn) {
    defer { conn.close() or {} }

    mut srv := jsonrpc.new_server(jsonrpc.ServerConfig{
        stream:  conn
        handler: handle_test
    })

    srv.start()
}

addr := '127.0.0.1:42228'
mut l := net.listen_tcp(.ip, addr)!
println('TCP JSON-RPC server on ${addr} (Content-Length framing)')

for {
    mut c := l.accept()!
    println('Accepted')
    go handle_conn(mut c)
}

Server can work with any io.ReaderWriter provided into stream field value. Server requires jsonrpc.Handler = fn(req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) to pass decoded jsonrpc.Request and to write jsonrpc.Response into jsonrpc.ResponseWriter. On Notification Server does call jsonrpc.Handler but it ingores written jsonrpc.Response.

Handler

jsonrpc.Handler = fn(req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) is the function that operates the decoded jsonrpc.Request and writes jsonrpc.Response into jsonrpc.ResponseWriter. Before every return wr.write() or wr.write_error() must be called so the server do not stuck waiting for jsonrpc.Response to be written. Also only wr.write() or wr.write_error() must be called before return and not both.

Router

The simple jsonrpc.Router is provided to register jsonrpc.Handler to handle specific method. The jsonrpc.Router.handle_jsonrpc must be passed into jsonrpc.Server.handler to handle requests. If jsonrpc.Request.method has no registered jsonrpc.Handler, the router will respond with jsonrpc.method_not_found error

Interceptors

Both jsonrpc.Client and jsonrpc.Server support jsonrpc.Interceptors - the collection of on event handlers. There is implementation of all supported interceptors called jsonrpc.LoggingInterceptor.