jsonrpc2

package module
v0.0.0-...-d6b2fc1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2021 License: Apache-2.0 Imports: 14 Imported by: 0

README

jsonrpc2

Go Reference

A full implementation of the JSON-RPC 2.0 specification, including support for request / response batches.

This library is EXPERIMENTAL and the API is not yet considered stable.

jsonrpc2 is designed to provide an API similar to what you would experience using Go's standard net/http package.

jsonrpc2 works with any io.ReadWriter, which enables you to use it over any transport, from tcp and websocket to stdin/stdout.

Roadmap

  • Bi-directional RPCs
  • Websockets
  • jsonrpc2 to gRPC shim

Example

// Program websocket is an example of jsonrpc2 using websocket. It implements an
// sum rpc service that will sum the params given to it.
//
// This can be tested using https://github.com/oliver006/ws-client:
//
//     $ ws-client ws://localhost:8080
//     [00:00] >> {"jsonrpc": "2.0", "method": "sum", "params": [1, 2, 3], "id": "1"}
//     [00:00] << {"jsonrpc": "2.0", "result": 6, "id": "1"}
package main

import (
  "encoding/json"
  "net/http"

  "github.com/chronly/jsonrpc2"
  "github.com/gorilla/websocket"
)

func main() {
  // Create a JSON-RPC 2 multiplexer and register a "sum" RPC handler.
  mux := jsonrpc2.NewServeMux()
  mux.HandleFunc("sum", func(w jsonrpc2.ResponseWriter, r *jsonrpc2.Request) {
    // Read in the parameters as a list of ints.
    var (
      input []int
      sum   int
    )
    if err := json.Unmarshal(r.Params, &input); err != nil {
      w.WriteError(jsonrpc2.ErrorInvalidParams, err)
      return
    }

    // Sum then together and write back out the result.
    for _, n := range input {
      sum += n
    }
    w.WriteMessage(sum)
  })

  // Start a websocket server on :8080.
  http.ListenAndServe("0.0.0.0:8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    var upgrader websocket.Upgrader
    wsConn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
      panic(err)
    }

    // NewWebsocketClient returns a Client which will automatically handle
    // incoming requests and send them to the provided handler. For our example,
    // we don't need to do anything with the client, but we could invoke RPC
    // methods on the client too for bi-directional RPCs.
    //
    // If the returned Client from NewWebsocketClient isn't closed, it will
    // automatically be closed when the websocket connection shuts down.
    jsonrpc2.NewWebsocketClient(wsConn, mux)
  }))
}

Documentation

Index

Constants

View Source
const (
	ErrorParse          int = -32700
	ErrorInvalidRequest int = -32600
	ErrorMethodNotFound int = -32601
	ErrorInvalidParams  int = -32602
	ErrorInternal       int = -32603
)

Error messages used by RPC calls. Error messages from -32768 and -32000 are reserved by the JSON-RPC 2.0 framework.

Variables

View Source
var DefaultHandler = NewServeMux()

DefaultHandler is the default handler used by a server. It returns ErrorMethodNotFound for each RPC.

Functions

This section is empty.

Types

type Batch

type Batch struct {
	// contains filtered or unexported fields
}

Batch is a batch of messages to send to a client. It must be committed with Commit. A Batch can be created through the Batch method on a Client.

func (*Batch) Commit

func (b *Batch) Commit(ctx context.Context) error

Commit commits the batch. If the response had any errors, the first error is returned.

func (*Batch) Invoke

func (b *Batch) Invoke(method string, msg interface{}) (*json.RawMessage, error)

Invoke queues an RPC to invoke. The returned *json.RawMessage will be empty until the batch is commited.

func (*Batch) Notify

func (b *Batch) Notify(method string, msg interface{}) error

Notify adds a notification request to the batch.

type Client

type Client struct {
	// contains filtered or unexported fields
}

func Dial

func Dial(target string, handler Handler, opts ...ClientOpt) (*Client, error)

Dial creates a connection to the target server using TCP. Handler will be invoked for each request received from the other side.

func NewClient

func NewClient(rw io.ReadWriter, handler Handler, opts ...ClientOpt) *Client

NewClient creates a client and starts reading messages from the provided io.ReadWriter. The given handler will be invoked for each request and notification that is read over rw.

If rw implements io.Closer, it will be closed when the Client is closed.

func NewWebsocketClient

func NewWebsocketClient(conn *websocket.Conn, handler Handler, opts ...ClientOpt) *Client

NewWebsocketClient creates a client from a Gorilla websocket. Closing the Client will close the underlying websocket.

This function wraps the websocket connection into a io.ReadWriteCloser and calls NewClient.

func (*Client) Batch

func (c *Client) Batch() *Batch

Batch creates a new request batch.

func (*Client) Close

func (c *Client) Close() error

Close closes the underlying transport.

func (*Client) Invoke

func (c *Client) Invoke(ctx context.Context, method string, msg interface{}) (json.RawMessage, error)

Invoke invokes an RPC on the other side of the connection and waits for a repsonse. Error will be set for RPC-level and transport-level problems.

RPC-level errors will be set to the Error object.

func (*Client) Notify

func (c *Client) Notify(method string, msg interface{}) error

Notify sends a notification request to the other side of the connection. It does not wait for a response, and there is no way of knowing if the other side succesfully handled the notification. An error will be returned for transport-level problems.

type ClientOpt

type ClientOpt func(*Client)

ClientOpt is an option function that can be passed to Dial and NewClient.

func WithClientLogger

func WithClientLogger(l log.Logger) ClientOpt

WithClientLogger sets the Client to use a logger.

type Error

type Error struct {
	Code    int             `json:"code"`
	Message string          `json:"message"`
	Data    json.RawMessage `json:"data,omitempty"`
}

Error is a JSON-RPC 2.0 Error object. It may be returned by Invoke.

func (Error) Error

func (e Error) Error() string

Error implements error.

type Handler

type Handler interface {
	// ServeRPC is invoked when an RPC call is received. If a response is needed
	// for a request, null will be sent as the response result. If the request is
	// a notification, ResponseWriter must NOT be used, even for delivering an
	// error.
	//
	// Written responses may not be delivered right away if the request is a batch
	// request.
	ServeRPC(w ResponseWriter, r *Request)
}

Handler handles an individual RPC call.

type HandlerFunc

type HandlerFunc func(w ResponseWriter, r *Request)

HandlerFunc implements Handler.

func (HandlerFunc) ServeRPC

func (f HandlerFunc) ServeRPC(w ResponseWriter, r *Request)

ServeRPC implements Handler.

type Request

type Request struct {
	// Notification indicates an asynchronous call from the server and responses
	// should not be written.
	Notification bool

	Method string
	Params json.RawMessage
	Client *Client
}

type ResponseWriter

type ResponseWriter interface {
	// WriteMessage writes a success response to the client. The value as provided
	// here will be marshaled to json. An error will be returned if the msg could
	// not be marshaled to JSON.
	WriteMessage(msg interface{}) error

	// WriteError writes an error response to the caller.
	WriteError(errorCode int, err error) error
}

type ServeMux

type ServeMux struct {
	// contains filtered or unexported fields
}

ServeMux is an RPC request multiplexer. It matches the method against a list of registered handlers and calls the handler whose method matches the request directly.

func NewServeMux

func NewServeMux() *ServeMux

NewServeMux allocates and returns a new ServeMux.

func (*ServeMux) Handle

func (m *ServeMux) Handle(method string, handler Handler)

Handle registers the handler for a given method. If a handler already exists for method, Handle panics.

func (*ServeMux) HandleFunc

func (m *ServeMux) HandleFunc(method string, handler func(rw ResponseWriter, r *Request))

HandleFunc registers the handler function for the given method.

func (*ServeMux) ServeRPC

func (m *ServeMux) ServeRPC(w ResponseWriter, req *Request)

ServeRPC implements Handler. ServeRPC will find a registered route matching the incoming request and invoke it if one exists. When a route wasn't found, ErrorMethodNotFound is returned to the caller.

type Server

type Server struct {
	// Handler is the handler to invoke when receiving a JSON-RPC request.
	Handler Handler

	// OnClient may be provided to handle new connections.
	OnClient func(c *Client)
	// contains filtered or unexported fields
}

Server is a JSON-RPC 2.0 server that can handle multiple conncurrent connections. For cases where only one connection is needed, use Client instead.

func (*Server) Close

func (s *Server) Close() error

Close closes the server. All listeners will be stopped.

func (*Server) Serve

func (s *Server) Serve(lis net.Listener) error

Serve starts serving connections from a listener. Each new connection will be created as a Client and will start processing messages.

lis will be closed when Serve exits.

If s.OnConn is non-nil, it will be invoked for each connection received.

Directories

Path Synopsis
examples
websocket
Program websocket is an example of jsonrpc2 using websocket.
Program websocket is an example of jsonrpc2 using websocket.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL