README

JRPC2GO: Zero dependencies JSON RPC 2.0 Library for Golang

JRPC2GO is a minimal API to handle JSON RPC 2.0 requests that works with transport layer that implements io.Reader and io.Writer.

Concepts

JRPC2Go works around two main concepts, the Manager and the Method.

Manager

The Manager is responsible for handling the requests and reply with responses, it also keeps all the methods supported and calls the right method for each request.

Once a request is received the Manager will validate the request, invoke the proper method and send back the response.

To create a new Manager we use the NewManagerBuilder that allows to create a new manager with the specified configuration ready to start handling requests.

manager := jrpc.NewManagerBuilder().
	SetTimeout(2*time.Second).
	Add("add", &addMethod{}).
	Add("sum", &addMethod{}).
	Build()

With the Manager ready we just need to call the Handle method from the manager and provide the input source (io.Reader), the output source (io.Writer) and the current context.

ctx := context.Background()
for {
	if err := manager.Handle(ctx, os.Stdin, os.Stdout); err != nil {
		if _, err := stdout.WriteString(err.Error()); err != nil {
			log.Fatal(err)
		}
	}
}

The example above connects the Manager to Stdin and Stdout, so we can send JSON-RPC requests and get the response from the terminal.

Method

The Method it's an interface with only one method called Execute

Execute(req *jrpc.Request, resp *jrpc.Response)

Inside this method we will put the operation "business-logic", from the Request we can get all the data sent from the client and also the request context and we put the result or error on the response.

type addMethod struct {
	// database and other resourses needed for this method
}

type addMethodParams struct {
	V1 int64 `json:"value1"`
	V2 int64 `json:"value2"`
}

func (m *addMethod) Execute(req *jrpc.Request, resp *jrpc.Response) {
	var p addMethodParams
	if err := req.ParseParams(&p); err != nil {
		resp.Error = err
		return
    }
    
	resp.Result = p.V1 + p.V2
}

The addMethod struct can contain the resources needed by the Execute and the addMethodParams it's the struct that represent the parameters sent on the request.

After that we jus need to add the method to the manager and it will take care of the rest.

manager := jrpc.NewManagerBuilder().
	Add("add", &addMethod{}).
	Build()

Installing

go get -u github.com/fabiodcorreia/jrpc2go

Next, include the package in your application:

import "github.com/fabiodcorreia/jrpc2go"

To make the package name less verbose it's recommended to use an alias:

import jrpc "github.com/fabiodcorreia/jrpc2go"

Examples

Examples full examples with HTTP and Stdin/out implementations can be found at _examples.

Contributing

  1. Fork it
  2. Clone your fork to your local machine (git clone https://github.com/your_username/jrpc2go && cd jsonrpc2go)
  3. Create your feature branch (git checkout -b my-new-feature)
  4. Make changes and add them (git add .)
  5. Commit your changes (git commit -m 'Add some feature')
  6. Push to the branch (git push origin my-new-feature)
  7. Create new pull request

License

JRPC2GO is released under the Apache 2.0 license. See LICENSE.txt

Expand ▾ Collapse ▴

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HTTPHandleFunc

func HTTPHandleFunc(m *Manager) func(w http.ResponseWriter, r *http.Request)

    HTTPHandleFunc it's an helper function to mediate http requests to JSON RPC and back.

    Types

    type Error

    type Error struct {
    	Code    ErrorCode   `json:"code"`
    	Message string      `json:"message"`
    	Data    interface{} `json:"data,omitempty"`
    }

      Error represents a JSON-RPC error, the Response MUST contain the error member if the RPC call encounters an error.

      Code - A Number that indicates the error type that occurred. This MUST be an integer.

      Message - A String providing a short description of the error. SHOULD be limited to a concise single sentence.

      Data - A Primitive or Structured value that contains additional information about the error.

      func (*Error) Error

      func (e *Error) Error() string

      type ErrorCode

      type ErrorCode int

        ErrorCode represents the API error number.

        type Manager

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

          Manager represent the JSON RPC method register manager.

          func (*Manager) Handle

          func (m *Manager) Handle(ctx context.Context, r io.Reader, w io.Writer) error

            Handle will receive a request content and write the result of the excecution to the writer.

            It can return an error if the JSON encoding or the writing fails.

            type ManagerBuilder

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

              ManagerBuilder will support the Builder pattern for the Manager struct.

              func NewManagerBuilder

              func NewManagerBuilder() *ManagerBuilder

                NewManagerBuilder will return a new builder for the Manager.

                func (*ManagerBuilder) Add

                func (mb *ManagerBuilder) Add(name string, h Method) *ManagerBuilder

                  Add will append a new method to the manager to be executed. the name should be unique if the name name is used more then one time it will overwrite the handler of that method.

                  If the name is empty or the h is nil this function will panic.

                  func (*ManagerBuilder) Build

                  func (mb *ManagerBuilder) Build() Manager

                    Build will use the configuration collected during the build return a manager with these configurations.

                    func (*ManagerBuilder) SetTimeout

                    func (mb *ManagerBuilder) SetTimeout(timeout time.Duration) *ManagerBuilder

                      SetTimeout allows to specify a custom timeout for each method execution.

                      Default timeout is 10 seconds

                      type Method

                      type Method interface {
                      	Execute(req *Request, resp *Response)
                      }

                        A Method responds to an JSON RPC request.

                        Execute should write reply result to the Response and then return. Returning signals that the request is finished

                        type Request

                        type Request struct {
                        	Version string           `json:"jsonrpc"`
                        	Method  string           `json:"method"`
                        	ID      *json.RawMessage `json:"id,omitempty"`
                        	Params  *json.RawMessage `json:"params,omitempty"`
                        	// contains filtered or unexported fields
                        }

                          Request represents a JSON-RPC call to the server and contains the following.

                          Version - A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".

                          Method - A String containing the name of the method to be invoked.

                          ID - An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null and Numbers SHOULD NOT contain fractional parts.

                          Params - A Structured value that holds the parameter values to be used during the invocation of the method.

                          func (*Request) Context

                          func (r *Request) Context() context.Context

                            Context returns the request's context. To change the context, use WithContext.

                            The returned context is always non-nil; it defaults to the background context.

                            func (*Request) ParseParams

                            func (r *Request) ParseParams(v interface{}) *Error

                              ParseParams will get the params from the request and and stores the result in the value pointed to by v.

                              Request.Params is optional but if we are calling the function they need to be there otherwise returns ErrInvalidParams.

                              func (*Request) WithContext

                              func (r *Request) WithContext(ctx context.Context) *Request

                                WithContext returns a shallow copy of r with its context changed to ctx. The provided ctx must be non-nil.

                                type Response

                                type Response struct {
                                	Version string           `json:"jsonrpc"`
                                	ID      *json.RawMessage `json:"id"`
                                	Result  interface{}      `json:"result,omitempty"`
                                	Error   *Error           `json:"error,omitempty"`
                                }

                                Response represents a JSON-RPC response from the server and containers the following.

                                Version - A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".

                                Result -

                                Error -

                                Directories

                                Path Synopsis
                                _examples