README

jsonrpc

GoDoc Go Go Report Card

Standards-compliant JSON-RPC 2.0 over HTTP for Go.

How to use

Create a new Handler and register methods to it. A method is any Go function with certain restrictions:

  • The method may contain a context.Context as its first argument.
  • The method must only have JSON-serializable arguments otherwise.
  • The method may return a JSON-serializable object as its first return value.
  • The method may return an error as its last return value.
  • The method must not have any other return values.

The JSON-RPC 2.0 handler only responds to POST requests.

h := jsonrpc.NewHandler()
h.RegisterMethod("echo", func (in string) string {
	return in
})
http.ListenAndServe(":8080", h)

Context

A method has access to the context.Context from the http.Request. A common use case is to use middleware to attach security credentials to the context, and then extract those credentials in the method to validate the user's authorization or return user-specific data.

h.RegisterMethod("secure", func(ctx context.Context) (string, error) {
	_, ok := ctx.Value("secure-cookie")
	if !ok {
		return "", fmt.Errorf("Invalid credentials.")
	}
	return "Top secret data", nil
})

JSON-RPC Errors

If you want to provide a JSON-RPC 2.0 error, use the Error struct. This lets you provide a custom error code and custom data.

h.RegisterMethod("bad", func (data json.RawMessage) error {
	return &jsonrpc.Error{
		Code: 101,
		Message: "This endpoint is bad.",
		Data: data,
	}
})

Multiple Registration

For convenience, you may register all methods on a value at once using Register.

a := SomeNewApi()
h.Register(a)

Motivation

When used this way, JSON-RPC 2.0 endpoints become self-documenting. They correspond exactly to their Go functions. They are testable.

This also allows almost any Go function to be used (unlike the built-in rpc/jsonrpc package in the Go standard library).

Expand ▾ Collapse ▴

Documentation

Overview

    Package jsonrpc implements the JSON-RPC 2.0 specification over HTTP.

    Regular functions can be registered to a Handler and then called using standard JSON-RPC 2.0 semantics. The only limitations on functions are as follows:

    - the first parameter may be a context.Context
    - the remaining parameters must be able to unmarshal from JSON
    - return values must be (optionally) a value and (optionally) an error
    - if there is a return value, it must be able to marshal as JSON
    

    Here is a simple example of a JSON-RPC 2.0 command that echos its input:

    h := jsonrpc.NewHandler()
    h.RegisterMethod("echo", func (in string) string { return in })
    http.ListenAndServe(":8080", h)
    

    You would call this over HTTP with standard JSON-RPC 2.0 semantics:

    => {"jsonrpc": "2.0", "id": 1, "method": "echo", "params": ["Hello world!"]}
    <= {"jsonrpc": "2.0", "id": 1, "result": "Hello world!"}
    

    As a convenience, structs may also be registered to a Handler. In this case, each method of the struct is registered using the method "Type.Method". For example:

    type Echo struct{}
    
    func (Echo) Echo(s string) string {
    	return s
    }
    
    func main() {
    	e := &Echo{}
    	h := jsonrpc.NewHandler()
    	h.Register(e)
    	http.ListenAndServe(":8080", h)
    }
    

    Then you would call this over HTTP as follows:

    => {"jsonrpc": "2.0", "id": 1, "method": "Echo.Echo", "params": ["Hello world!"]}
    <= {"jsonrpc": "2.0", "id": 1, "result": "Hello world!"}
    

    As a further convenience, you may pass in one or more structs into the NewHandler constructor. For example:

    http.ListenAndServe(":8080", jsonrpc.NewHandler(&Echo{}))
    

    Index

    Constants

    View Source
    const (
    	StatusParseError     = -32700 // Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.
    	StatusInvalidRequest = -32600 // The JSON sent is not a valid Request object.
    	StatusMethodNotFound = -32601 // The method does not exist / is not available.
    	StatusInvalidParams  = -32602 // Invalid method parameter(s).
    	StatusInternalError  = -32603 // Internal JSON-RPC error.
    )

      JSON-RPC 2.0 reserved status codes.

      Variables

      This section is empty.

      Functions

      This section is empty.

      Types

      type Encoder

      type Encoder interface {
      	Encode(v interface{}) error
      }

        Encoder is something that can encode into JSON. By default it is a json.Encoder

        type Error

        type Error struct {
        	Code    int         `json:"code"`
        	Message string      `json:"message"`
        	Data    interface{} `json:"data"`
        	// contains filtered or unexported fields
        }

          Error represents a JSON-RPC 2.0 error. If an Error is returned from a registered function, it will be sent directly to the client.

          func WrapError

          func WrapError(err error) *Error

            WrapError creates a JSON-RPC Error by wrapping an underlying error, with StatusInternalError by default. If the wrapped error is also a JSON-RPC error, then it is preserved.

            func (*Error) Error

            func (err *Error) Error() string

            func (*Error) Unwrap

            func (err *Error) Unwrap() error

            type Handler

            type Handler struct {
            	// Encoder configures what encoder will be used for sending JSON-RPC
            	// responses. By default the Handler will use json.NewEncoder.
            	Encoder func(w io.Writer) Encoder
            
            	// RequestInterceptor, if specified, will be called after the JSON-RPC
            	// message is parsed but before the method is called. The Request may be
            	// modified.
            	//
            	// This can be used, for example, to perform handler-wide validation.
            	//
            	// If an error is returned, the method is never called and that error will
            	// be sent to the client instead.
            	RequestInterceptor func(ctx context.Context, req *Request) error
            
            	// ResponseInterceptor, if specified, will be called after the method is
            	// called but before the response is sent to the client. The Response may
            	// be modified.
            	//
            	// If an error is returned, that error will be sent to the client instead.
            	ResponseInterceptor func(ctx context.Context, req Request, res *Response) error
            	// contains filtered or unexported fields
            }

              Handler is an http.Handler that responds to JSON-RPC 2.0 requests.

              func NewHandler

              func NewHandler(rcvrs ...interface{}) *Handler

                NewHandler initializes a new Handler. If receivers are provided, they will be registered.

                func (*Handler) Register

                func (h *Handler) Register(rcvr interface{})

                  Register is a convenience function. It will call RegisterMethod on each method of the provided receiver. The registered method name will follow the pattern "Type.Method".

                  func (*Handler) RegisterMethod

                  func (h *Handler) RegisterMethod(name string, fn interface{})

                    RegisterMethod registers a method under the given name. Methods must be valid functions with the following restrictions:

                    - the first parameter may be a context.Context
                    - the remaining parameters must be able to unmarshal from JSON
                    - return values must be (optionally) a value and (optionally) an error
                    - if there is a return value, it must be able to marshal as JSON
                    

                    If the first parameter is a context.Context, then it will receive the context from the HTTP request.

                    func (*Handler) RegisterName

                    func (h *Handler) RegisterName(name string, rcvr interface{})

                      RegisterName is like Register but uses the provided name for the type instead of the receiver's concrete type.

                      func (*Handler) ServeConn

                      func (h *Handler) ServeConn(ctx context.Context, rw io.ReadWriter)

                        ServeConn provides JSON-RPC over any bi-directional stream.

                        func (*Handler) ServeHTTP

                        func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

                        type Request

                        type Request struct {
                        	Method string
                        	Params json.RawMessage
                        }

                          Request is unmarshalled before every JSON-RPC call. It contains the raw message and params from the JSON-RPC message.

                          type Response

                          type Response struct {
                          	Result interface{}
                          	Error  *Error
                          }

                            Response contains the results of a JSON-RPC call, and will be marshalled as a JSON-RPC message.

                            Source Files