jsonrpc

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: May 9, 2023 License: Apache-2.0, MIT Imports: 32 Imported by: 312

README

go-jsonrpc

go.dev reference

Low Boilerplate JSON-RPC 2.0 library

Usage examples

Server
// Have a type with some exported methods
type SimpleServerHandler struct {
    n int
}

func (h *SimpleServerHandler) AddGet(in int) int {
    h.n += in
    return h.n
}

func main() {
    // create a new server instance
    rpcServer := jsonrpc.NewServer()
    
    // create a handler instance and register it
    serverHandler := &SimpleServerHandler{}
    rpcServer.Register("SimpleServerHandler", serverHandler)
    
    // rpcServer is now http.Handler which will serve jsonrpc calls to SimpleServerHandler.AddGet
    // a method with a single int param, and an int response. The server supports both http and websockets.
    
    // serve the api
    testServ := httptest.NewServer(rpcServer)
    defer testServ.Close()
	
    fmt.Println("URL: ", "ws://"+testServ.Listener.Addr().String())
    
    [..do other app stuff / wait..]
}
Client
func start() error {
    // Create a struct where each field is an exported function with signatures matching rpc calls
    var client struct {
        AddGet      func(int) int
    }
	
	// Make jsonrp populate func fields in the struct with JSONRPC calls
    closer, err := jsonrpc.NewClient(context.Background(), rpcURL, "SimpleServerHandler", &client, nil)
    if err != nil {
    	return err
    }
    defer closer()
    
    ...
    
    n := client.AddGet(10)
    // if the server is the one from the example above, n = 10

    n := client.AddGet(2)
    // if the server is the one from the example above, n = 12
}
Supported function signatures
type _ interface {
    // No Params / Return val
    Func1()
    
    // With Params
    // Note: If param types implement json.[Un]Marshaler, go-jsonrpc will use it
    Func2(param1 int, param2 string, param3 struct{A int})
    
    // Returning errors
    // * For some connection errors, go-jsonrpc will return jsonrpc.RPCConnectionError{}.
    // * RPC-returned errors will be constructed with basic errors.New(__"string message"__)
    // * JSON-RPC error codes can be mapped to typed errors with jsonrpc.Errors - https://pkg.go.dev/github.com/filecoin-project/go-jsonrpc#Errors
    // * For typed errors to work, server needs to be constructed with the `WithServerErrors`
    //   option, and the client needs to be constructed with the `WithErrors` option
    Func3() error
    
    // Returning a value
    // Note: The value must be serializable with encoding/json.
    Func4() int
    
    // Returning a value and an error
    // Note: if the handler returns an error and a non-zero value, the value will not
    //       be returned to the client - the client will see a zero value.
    Func4() (int, error)
    
    // With context
    // * Context isn't passed as JSONRPC param, instead it has a number of different uses
    // * When the context is cancelled on the client side, context cancellation should propagate to the server handler
    //   * In http mode the http request will be aborted
    //   * In websocket mode the client will send a `xrpc.cancel` with a single param containing ID of the cancelled request
    // * If the context contains an opencensus trace span, it will be propagated to the server through a
    //   `"Meta": {"SpanContext": base64.StdEncoding.EncodeToString(propagation.Binary(span.SpanContext()))}` field in
    //   the jsonrpc request
    //   
    Func5(ctx context.Context, param1 string) error
    
    // With non-json-serializable (e.g. interface) params
    // * There are client and server options which make it possible to register transformers for types
    //   to make them json-(de)serializable
    // * Server side: jsonrpc.WithParamDecoder(new(io.Reader), func(ctx context.Context, b []byte) (reflect.Value, error) { ... }
    // * Client side: jsonrpc.WithParamEncoder(new(io.Reader), func(value reflect.Value) (reflect.Value, error) { ... }
    // * For io.Reader specifically there's a simple param encoder/decoder implementation in go-jsonrpc/httpio package
    //   which will pass reader data through separate http streams on a different hanhler.
    // * Note: a similar mechanism for return value transformation isn't supported yet
    Func6(r io.Reader)
    
    // Returning a channel
    // * Only supported in websocket mode
    // * If no error is returned, the return value will be an int channelId
    // * When the server handler writes values into the channel, the client will receive `xrpc.ch.val` notifications
    //   with 2 params: [chanID: int, value: any]
    // * When the channel is closed the client will receive `xrpc.ch.close` notification with a single param: [chanId: int]
    // * The client-side channel will be closed when the websocket connection breaks; Server side will discard writes to
    //   the channel. Handlers should rely on the context to know when to stop writing to the returned channel.
    // NOTE: There is no good backpressure mechanism implemented for channels, returning values faster that the client can
    // receive them may cause memory leaks.
    Func7(ctx context.Context, param1 int, param2 string) (<-chan int, error)
}

Contribute

PRs are welcome!

License

Dual-licensed under MIT + Apache 2.0

Documentation

Index

Constants

View Source
const (
	ProxyTagRetry     = "retry"
	ProxyTagNotify    = "notify"
	ProxyTagRPCMethod = "rpc_method"
)
View Source
const DEFAULT_MAX_REQUEST_SIZE = 100 << 20 // 100 MiB

Limit request size. Ideally this limit should be specific for each field in the JSON request but as a simple defensive measure we just limit the entire HTTP body. Configured by WithMaxRequestSize.

View Source
const FirstUserCode = 2

Variables

This section is empty.

Functions

func DecodeParams added in v0.2.0

func DecodeParams[T any](p RawParams) (T, error)

todo is there a better way to tell 'struct with any number of fields'?

func ExtractReverseClient added in v0.2.0

func ExtractReverseClient[C any](ctx context.Context) (C, bool)

ExtractReverseClient will extract reverse client from context. Reverse client for the type will only be present if the server was constructed with a matching WithReverseClient option and the connection was a websocket connection. If there is no reverse client, the call will return a zero value and `false`. Otherwise a reverse client and `true` will be returned.

func WithClientHandler added in v0.2.0

func WithClientHandler(ns string, hnd interface{}) func(c *Config)

func WithClientHandlerAlias added in v0.2.0

func WithClientHandlerAlias(alias, original string) func(c *Config)

WithClientHandlerAlias creates an alias for a client HANDLER method - for handlers created with WithClientHandler

func WithErrors added in v0.1.6

func WithErrors(es Errors) func(c *Config)

func WithHTTPClient added in v0.2.0

func WithHTTPClient(h *http.Client) func(c *Config)

func WithNoReconnect added in v0.1.2

func WithNoReconnect() func(c *Config)

func WithParamEncoder added in v0.1.1

func WithParamEncoder(t interface{}, encoder ParamEncoder) func(c *Config)

func WithPingInterval added in v0.1.2

func WithPingInterval(d time.Duration) func(c *Config)

Must be < Timeout/2

func WithReconnectBackoff added in v0.1.1

func WithReconnectBackoff(minDelay, maxDelay time.Duration) func(c *Config)

func WithTimeout added in v0.1.2

func WithTimeout(d time.Duration) func(c *Config)

Types

type ClientCloser

type ClientCloser func()

ClientCloser is used to close Client from further use

func NewClient

func NewClient(ctx context.Context, addr string, namespace string, handler interface{}, requestHeader http.Header) (ClientCloser, error)

NewClient creates new jsonrpc 2.0 client

handler must be pointer to a struct with function fields Returned value closes the client connection TODO: Example

func NewMergeClient

func NewMergeClient(ctx context.Context, addr string, namespace string, outs []interface{}, requestHeader http.Header, opts ...Option) (ClientCloser, error)

NewMergeClient is like NewClient, but allows to specify multiple structs to be filled in the same namespace, using one connection

type Config

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

type ErrClient

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

ErrClient is an error which occurred on the client side the library

func (*ErrClient) Error

func (e *ErrClient) Error() string

func (*ErrClient) Unwrap

func (e *ErrClient) Unwrap() error

Unwrap unwraps the actual error

type ErrorCode added in v0.1.6

type ErrorCode int

type Errors added in v0.1.6

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

func NewErrors added in v0.1.6

func NewErrors() Errors

func (*Errors) Register added in v0.1.6

func (e *Errors) Register(c ErrorCode, typ interface{})

type Option

type Option func(c *Config)

type ParamDecoder added in v0.1.1

type ParamDecoder func(ctx context.Context, json []byte) (reflect.Value, error)

type ParamEncoder added in v0.1.1

type ParamEncoder func(reflect.Value) (reflect.Value, error)

type RPCConnectionError added in v0.1.7

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

func (*RPCConnectionError) Error added in v0.1.7

func (e *RPCConnectionError) Error() string

func (*RPCConnectionError) Unwrap added in v0.1.7

func (e *RPCConnectionError) Unwrap() error

type RPCServer

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

RPCServer provides a jsonrpc 2.0 http server handler

func NewServer

func NewServer(opts ...ServerOption) *RPCServer

NewServer creates new RPCServer instance

func (*RPCServer) AliasMethod added in v0.1.2

func (s *RPCServer) AliasMethod(alias, original string)

func (*RPCServer) Register

func (s *RPCServer) Register(namespace string, handler interface{})

Register registers new RPC handler

Handler is any value with methods defined

func (*RPCServer) ServeHTTP

func (s *RPCServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

TODO: return errors to clients per spec

type RawParams added in v0.2.0

type RawParams json.RawMessage

type ServerConfig added in v0.1.1

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

type ServerOption added in v0.1.1

type ServerOption func(c *ServerConfig)

func WithMaxRequestSize added in v0.1.2

func WithMaxRequestSize(max int64) ServerOption

func WithParamDecoder added in v0.1.1

func WithParamDecoder(t interface{}, decoder ParamDecoder) ServerOption

func WithReverseClient added in v0.2.0

func WithReverseClient[RP any](namespace string) ServerOption

WithReverseClient will allow extracting reverse client on **WEBSOCKET** calls. RP is a proxy-struct type, much like the one passed to NewClient.

func WithServerErrors added in v0.1.6

func WithServerErrors(es Errors) ServerOption

func WithServerPingInterval added in v0.2.0

func WithServerPingInterval(d time.Duration) ServerOption

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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