jsonrpc

package module
Version: v0.0.0-...-352acaa Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2020 License: MIT Imports: 10 Imported by: 12

README

jsonrpc

GitHub Actions codecov Go Report Card codebeat badge Maintainability GoDoc GitHub license

About

  • Simple, Poetic, Pithy.
  • No reflect package.
    • But reflect package is used only when invoke the debug handler.
  • Support GAE/Go Standard Environment.
  • Compliance with JSON-RPC 2.0.

Note: If you use Go 1.6, see v1.0.

Install

$ go get -u github.com/osamingo/jsonrpc

Usage

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/intel-go/fastjson"
	"github.com/osamingo/jsonrpc"
)

type (
	EchoHandler struct{}
	EchoParams  struct {
		Name string `json:"name"`
	}
	EchoResult struct {
		Message string `json:"message"`
	}

	PositionalHandler struct{}
	PositionalParams  []int
	PositionalResult  struct {
		Message []int `json:"message"`
	}
)

func (h EchoHandler) ServeJSONRPC(c context.Context, params *fastjson.RawMessage) (interface{}, *jsonrpc.Error) {

	var p EchoParams
	if err := jsonrpc.Unmarshal(params, &p); err != nil {
		return nil, err
	}

	return EchoResult{
		Message: "Hello, " + p.Name,
	}, nil
}

func (h PositionalHandler) ServeJSONRPC(c context.Context, params *fastjson.RawMessage) (interface{}, *Error) {

	var p PositionalParams
	if err := jsonrpc.Unmarshal(params, &p); err != nil {
		return nil, err
	}

	return PositionalResult{
		Message: p,
	}, nil
}

func main() {

	mr := jsonrpc.NewMethodRepository()

	if err := mr.RegisterMethod("Main.Echo", EchoHandler{}, EchoParams{}, EchoResult{}); err != nil {
		log.Fatalln(err)
	}

	if err := mr.RegisterMethod("Main.Positional", PositionalHandler{}, PositionalParams{}, PositionalResult{}); err != nil {
		log.Fatalln(err)
	}

	http.Handle("/jrpc", mr)
	http.HandleFunc("/jrpc/debug", mr.ServeDebug)

	if err := http.ListenAndServe(":8080", http.DefaultServeMux); err != nil {
		log.Fatalln(err)
	}
}
Advanced
package main

import (
	"log"
	"net/http"

	"github.com/osamingo/jsonrpc"
)

type (
	HandleParamsResulter interface {
		jsonrpc.Handler
		Name() string
		Params() interface{}
		Result() interface{}
	}
	Servicer interface {
		MethodName(HandleParamsResulter) string
		Handlers() []HandleParamsResulter
	}
	UserService struct {
		SignUpHandler HandleParamsResulter
		SignInHandler HandleParamsResulter
	}
)

func (us *UserService) MethodName(h HandleParamsResulter) string {
	return "UserService." + h.Name()
}

func (us *UserService) Handlers() []HandleParamsResulter {
	return []HandleParamsResulter{us.SignUpHandler, us.SignInHandler}
}

func NewUserService() *UserService {
	return &UserService{
	// Initialize handlers
	}
}

func main() {

	mr := jsonrpc.NewMethodRepository()

	for _, s := range []Servicer{NewUserService()} {
		for _, h := range s.Handlers() {
			mr.RegisterMethod(s.MethodName(h), h, h.Params(), h.Result())
		}
	}

	http.Handle("/jrpc", mr)
	http.HandleFunc("/jrpc/debug", mr.ServeDebug)

	if err := http.ListenAndServe(":8080", http.DefaultServeMux); err != nil {
		log.Fatalln(err)
	}
}
Result
Invoke the Echo method
POST /jrpc HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 82
Content-Type: application/json
Host: localhost:8080
User-Agent: HTTPie/0.9.6

{
  "jsonrpc": "2.0",
  "method": "Main.Echo",
  "params": {
    "name": "John Doe"
  },
  "id": "243a718a-2ebb-4e32-8cc8-210c39e8a14b"
}

HTTP/1.1 200 OK
Content-Length: 68
Content-Type: application/json
Date: Mon, 28 Nov 2016 13:48:13 GMT

{
  "jsonrpc": "2.0",
  "result": {
    "message": "Hello, John Doe"
  },
  "id": "243a718a-2ebb-4e32-8cc8-210c39e8a14b"
}
Invoke the Positional method
POST /jrpc HTTP/1.1
Accept: */*
Content-Length: 133
Content-Type: application/json
Host: localhost:8080
User-Agent: curl/7.61.1

{
  "jsonrpc": "2.0",
  "method": "Main.Positional",
  "params": [3,1,1,3,5,3],
  "id": "243a718a-2ebb-4e32-8cc8-210c39e8a14b"
}

HTTP/1.1 200 OK
Content-Length: 97
Content-Type: application/json
Date: Mon, 05 Nov 2018 11:23:35 GMT

{
  "jsonrpc": "2.0",
  "result": {
    "message": [3,1,1,3,5,3]
  },
  "id": "243a718a-2ebb-4e32-8cc8-210c39e8a14b"
}

Access to debug handler
GET /jrpc/debug HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.6

HTTP/1.1 200 OK
Content-Length: 408
Content-Type: application/json
Date: Mon, 28 Nov 2016 13:56:24 GMT

[
  {
    "handler": "EchoHandler",
    "name": "Main.Echo",
    "params": {
      "$ref": "#/definitions/EchoParams",
      "$schema": "http://json-schema.org/draft-04/schema#",
      "definitions": {
        "EchoParams": {
          "additionalProperties": false,
          "properties": {
            "name": {
              "type": "string"
            }
          },
          "required": [
            "name"
          ],
          "type": "object"
        }
      }
    },
    "result": {
      "$ref": "#/definitions/EchoResult",
      "$schema": "http://json-schema.org/draft-04/schema#",
      "definitions": {
        "EchoResult": {
          "additionalProperties": false,
          "properties": {
            "message": {
              "type": "string"
            }
          },
          "required": [
            "message"
          ],
          "type": "object"
        }
      }
    }
  }
]

License

Released under the MIT License.

Documentation

Overview

Package jsonrpc helps JSON-RPC 2.0 implements.

Index

Constants

View Source
const (
	// Version is JSON-RPC 2.0.
	Version = "2.0"
)

Variables

This section is empty.

Functions

func MethodName

func MethodName(c context.Context) string

MethodName takes method name from context.

func ParseRequest

func ParseRequest(r *http.Request) ([]*Request, bool, *Error)

ParseRequest parses a HTTP request to JSON-RPC request.

func RequestID

func RequestID(c context.Context) *fastjson.RawMessage

RequestID takes request id from context.

func SendResponse

func SendResponse(w http.ResponseWriter, resp []*Response, batch bool) error

SendResponse writes JSON-RPC response.

func WithMetadata

func WithMetadata(c context.Context, md Metadata) context.Context

WithMetadata adds jsonrpc metadata to context.

func WithMethodName

func WithMethodName(c context.Context, name string) context.Context

WithMethodName adds method name to context.

func WithRequestID

func WithRequestID(c context.Context, id *fastjson.RawMessage) context.Context

WithRequestID adds request id to context.

Types

type Error

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

An Error is a wrapper for a JSON interface value.

func ErrInternal

func ErrInternal() *Error

ErrInternal returns internal error.

func ErrInvalidParams

func ErrInvalidParams() *Error

ErrInvalidParams returns invalid params error.

func ErrInvalidRequest

func ErrInvalidRequest() *Error

ErrInvalidRequest returns invalid request error.

func ErrMethodNotFound

func ErrMethodNotFound() *Error

ErrMethodNotFound returns method not found error.

func ErrParse

func ErrParse() *Error

ErrParse returns parse error.

func Unmarshal

func Unmarshal(params *fastjson.RawMessage, dst interface{}) *Error

Unmarshal decodes JSON-RPC params.

func (*Error) Error

func (e *Error) Error() string

Error implements error interface.

type ErrorCode

type ErrorCode int

A ErrorCode by JSON-RPC 2.0.

const (
	// ErrorCodeParse is parse error code.
	ErrorCodeParse ErrorCode = -32700
	// ErrorCodeInvalidRequest is invalid request error code.
	ErrorCodeInvalidRequest ErrorCode = -32600
	// ErrorCodeMethodNotFound is method not found error code.
	ErrorCodeMethodNotFound ErrorCode = -32601
	// ErrorCodeInvalidParams is invalid params error code.
	ErrorCodeInvalidParams ErrorCode = -32602
	// ErrorCodeInternal is internal error code.
	ErrorCodeInternal ErrorCode = -32603
)

type Handler

type Handler interface {
	ServeJSONRPC(c context.Context, params *fastjson.RawMessage) (result interface{}, err *Error)
}

Handler links a method of JSON-RPC request.

type HandlerFunc

type HandlerFunc func(c context.Context, params *fastjson.RawMessage) (result interface{}, err *Error)

HandlerFunc type is an adapter to allow the use of ordinary functions as JSONRPC handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a jsonrpc.Handler that calls f.

func (HandlerFunc) ServeJSONRPC

func (f HandlerFunc) ServeJSONRPC(c context.Context, params *fastjson.RawMessage) (result interface{}, err *Error)

ServeJSONRPC calls f(w, r).

type Metadata

type Metadata struct {
	Handler Handler
	Params  interface{}
	Result  interface{}
}

Metadata has method meta data.

func GetMetadata

func GetMetadata(c context.Context) Metadata

GetMetadata takes jsonrpc metadata from context.

type MethodReference

type MethodReference struct {
	Name    string             `json:"name"`
	Handler string             `json:"handler"`
	Params  *jsonschema.Schema `json:"params,omitempty"`
	Result  *jsonschema.Schema `json:"result,omitempty"`
}

A MethodReference is a reference of JSON-RPC method.

type MethodRepository

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

A MethodRepository has JSON-RPC method functions.

func NewMethodRepository

func NewMethodRepository() *MethodRepository

NewMethodRepository returns new MethodRepository.

func (*MethodRepository) InvokeMethod

func (mr *MethodRepository) InvokeMethod(c context.Context, r *Request) *Response

InvokeMethod invokes JSON-RPC method.

func (*MethodRepository) Methods

func (mr *MethodRepository) Methods() map[string]Metadata

Methods returns registered methods.

func (*MethodRepository) RegisterMethod

func (mr *MethodRepository) RegisterMethod(method string, h Handler, params, result interface{}) error

RegisterMethod registers jsonrpc.Func to MethodRepository.

func (*MethodRepository) ServeDebug

func (mr *MethodRepository) ServeDebug(w http.ResponseWriter, r *http.Request)

ServeDebug views registered method list.

func (*MethodRepository) ServeHTTP

func (mr *MethodRepository) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP provides basic JSON-RPC handling.

func (*MethodRepository) TakeMethod

func (mr *MethodRepository) TakeMethod(r *Request) (Handler, *Error)

TakeMethod takes jsonrpc.Func in MethodRepository.

func (*MethodRepository) TakeMethodMetadata

func (mr *MethodRepository) TakeMethodMetadata(r *Request) (Metadata, *Error)

TakeMethodMetadata takes metadata in MethodRepository for request.

type Request

type Request struct {
	Version string               `json:"jsonrpc"`
	Method  string               `json:"method"`
	Params  *fastjson.RawMessage `json:"params"`
	ID      *fastjson.RawMessage `json:"id"`
}

A Request represents a JSON-RPC request received by the server.

type Response

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

A Response represents a JSON-RPC response returned by the server.

func NewResponse

func NewResponse(r *Request) *Response

NewResponse generates a JSON-RPC response.

Jump to

Keyboard shortcuts

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