Skip to content

go-pkgz/jrpc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

1b265f7 · Apr 15, 2025

History

45 Commits
Dec 17, 2024
Jan 12, 2025
Jul 30, 2019
Apr 15, 2025
Feb 8, 2020
Nov 29, 2021
Jul 19, 2022
Nov 29, 2021
Apr 15, 2025
Apr 15, 2025
Jul 31, 2019
Nov 29, 2021
Apr 15, 2025
Jul 19, 2022

Repository files navigation

jrpc - rpc with json Build Go Report Card Coverage Status godoc

jrpc library provides client and server for RPC-like communication over HTTP with json encoded messages. The protocol is a somewhat simplified version of json-rpc with a single POST call sending Request json (method name and the list of parameters) moreover, receiving json Response with result data and an error string.

Usage

Plugin (server)

// Plugin wraps jrpc.Server and adds synced map to store data
type Plugin struct {
	*jrpc.Server
}

// create plugin (jrpc server) with NewServer where required param is a base url for rpc calls
plugin := NewServer("/command")

// then add you function to map 
plugin.Add("mycommand", func(id uint64, params json.RawMessage) Response {
    return jrpc.EncodeResponse(id, "hello, it works", nil)
})

// and run server with port number value
plugin.Run(9090)

The constructor NewServer accept two parameters:

  • API - a base url for rpc calls
  • Options - optional parameters such is timeouts, logger, limits, middlewares and etc.
    • Auth - set credentials basic auth to server, accepts username and password
    • WithTimeout - sets global timeouts for server requests, such as read, write and idle. Call accept Timeouts struct.
    • WithLimits - define limit for server call, accepts limit value in float64 type
    • WithThrottler - sets throttler middleware with specify limit value
    • WithtSignature - sets server signature, accept appName, author and version. Disable by default.
    • WithLogger - define custom logger (e.g. lgr)
    • WithMiddlewares - sets custom middlewares list to server, accepts list of handler with idiomatic type func(http.Handler) http.Handler

Example with options:

plugin := NewServer("/command",
	    Auth("user", "password"),
		WithTimeout(Timeouts{ReadHeaderTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, IdleTimeout: 10 * time.Second}),
		WithThrottler(120),
		WithLimits(100),
        WithtSignature("the best plugin ever", "author", "1.0.0"),
		WithMiddlewares(middleware.Heartbeat('/ping'), middleware.Profiler, middleware.StripSlashes),
)

Application (client)

// Client makes jrpc.Client and invoke remote call
rpcClient := jrpc.Client{
    API:        "http://127.0.0.1:8080/command",
    Client:     http.Client{},
    AuthUser:   "user",
    AuthPasswd: "password",
}

resp, err := rpcClient.Call("mycommand")
var message string
if err = json.Unmarshal(*resp.Result, &message); err != nil {
    panic(err)
}

for functional examples for both plugin and application see _example

Technical details

  • jrpc.Server runs on user-defined port as a regular http server
  • Server accepts a single POST request on user-defined url with Request sent as json payload
request details and an example:
 ```go
 type Request struct {
 	Method string      `json:"method"`
 	Params interface{} `json:"params,omitempty"`
 	ID     uint64      `json:"id"`
 }
 ```
 example: 
 
 ```json
   {
    "method":"test",
    "params":[123,"abc"],
    "id":1
    }
 ```
  • Params can be a struct, primitive type or slice of values, even with different types.
  • Server defines ServerFn handler function to react on a POST request. The handler provided by the user.
  • Communication between the server and the caller can be protected with basic auth.
  • Client provides a single method Call and return Response
response details:
 // Response encloses result and error received from remote server
 type Response struct {
 	Result *json.RawMessage `json:"result,omitempty"`
 	Error  string           `json:"error,omitempty"`
 	ID     uint64           `json:"id"`
 }
  • User should encode and decode json payloads on the application level, see provided examples
  • jrpc.Server doesn't support https internally (yet). If used on exposed or non-private networks, should be proxied with something providing https termination (nginx and others).

Status

The code was extracted from remark42 and still under development. Until v1.x released the API & protocol may change.