jsonrpc

package module
v0.0.0-...-32aa047 Latest Latest
Warning

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

Go to latest
Published: Dec 3, 2018 License: MIT Imports: 10 Imported by: 0

README

jsonrpc

Go Report Card codebeat badge Maintainability GoDoc GitHub license

About

  • Forked from osamingo/jsonrpc
  • Add Middleware
  • 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/IcanFun/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"`
	}
	
	MiddlewareHandler struct{}

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

func (h EchoHandler) ServeJSONRPC(c *jsonrpc.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 MiddlewareHandler) ServeJSONRPC(c *Context, params *fastjson.RawMessage) (interface{}, *Error) {

	var p PositionalParams
	if err := Unmarshal(params, &p); err != nil {
		return nil, err
	}
	log.Printf("%+v", p)

	return nil, nil
}

func (h PositionalHandler) ServeJSONRPC(c *jsonrpc.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", EchoParams{}, EchoResult{},EchoHandler{}); err != nil {
		log.Fatalln(err)
	}

	if err := mr.RegisterMethod("Main.Positional", PositionalParams{}, PositionalResult{}, MiddlewareHandler{}, PositionalHandler{}); 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()
	
	mr.Use(func(context *jsonrpc.Context) (err *Error) {
		req := map[string]interface{}{}
		if err := json.Unmarshal(context.Body(), &req); err != nil {
			return ErrParse()
		}
		log.Printf("middleware %s", req)
		context.Next()
		return nil
	})
	
	for _, s := range []Servicer{NewUserService()} {
		for _, h := range s.Handlers() {
			mr.RegisterMethod(s.MethodName(h), h.Params(), h.Result(),h)
		}
	}

	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 ParseRequest

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

ParseRequest parses a HTTP request to JSON-RPC request.

func SendResponse

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

SendResponse writes JSON-RPC response.

Types

type Context

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

Context body is http post data

func WithRequestID

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

WithRequestID adds request id to context.

func (*Context) Abort

func (c *Context) Abort()

Abort middleware invokes, JSON-RPC stop

func (*Context) Body

func (c *Context) Body() []byte

Body get body

func (*Context) Context

func (c *Context) Context() context.Context

Context get context

func (*Context) IsNext

func (c *Context) IsNext() bool

IsNext can the JSON-RPC continue, default is true

func (*Context) Next

func (c *Context) Next()

Next middleware invokes, JSON-RPC continue

func (*Context) RequestID

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

RequestID takes request id from context.

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, params *fastjson.RawMessage) (result interface{}, err *Error)
}

Handler links a method of JSON-RPC request.

type HandlerChain

type HandlerChain []Handler

HandlerChain is Handler slice

type Metadata

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

Metadata has method meta data.

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 {
	Middlewares MiddlewareChain
	// 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, r *Request) *Response

InvokeMethod invokes JSON-RPC method.

func (*MethodRepository) InvokeMiddleware

func (mr *MethodRepository) InvokeMiddleware(c Context, r *Request) *Response

InvokeMiddleware invokes middleware method

func (*MethodRepository) Methods

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

Methods returns registered methods.

func (*MethodRepository) RegisterMethod

func (mr *MethodRepository) RegisterMethod(method string, params, result interface{}, h ...Handler) 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) (HandlerChain, *Error)

TakeMethod takes jsonrpc.Func in MethodRepository.

func (*MethodRepository) Use

func (mr *MethodRepository) Use(middleware ...MiddlewareFunc)

Use registers middleware function

type MiddlewareChain

type MiddlewareChain []MiddlewareFunc

MiddlewareChain middleware function slice

type MiddlewareFunc

type MiddlewareFunc func(*Context) (err *Error)

MiddlewareFunc ... middleware function

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