The jsonrpc package helps implement of JSON-RPC 2.0

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/v2

Usage

package main

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

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

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/v2"
)

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.

Owner
Osamu TONOMORI
I'm an Engineering Manager and a Technical Program Manager working in the FinTech corp. I'm supported by some ventures on the side work.
Osamu TONOMORI
Comments
  • Cannot get latest version: module contains a go.mod file, so module path should be github.com/osamingo/jsonrpc/v2

    Cannot get latest version: module contains a go.mod file, so module path should be github.com/osamingo/jsonrpc/v2

    Background

    The github.com/osamingo/jsonrpc uses Go modules and the current release version is v2. And it’s module path is "github.com/osamingo/jsonrpc", instead of "github.com/osamingo/jsonrpc/v2". It must comply with the specification of "Releasing Modules for v2 or higher" available in the Modules documentation. Quoting the specification:

    A package that has opted in to modules must include the major version in the import path to import any v2+ modules To preserve import compatibility, the go command requires that modules with major version v2 or later use a module path with that major version as the final element. For example, version v2.0.0 of example.com/m must instead use module path example.com/m/v2. https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher

    Steps to Reproduce

    GO111MODULE=on, run go get targeting any version >= v2.2.0 of the osamingo/jsonrpc:

    $ go get github.com/osamingo/[email protected]
    go: finding github.com/osamingo/jsonrpc v2.3.0
    go: finding github.com/osamingo/jsonrpc v2.3.0
    go get github.com/osamingo/[email protected]: github.com/osamingo/[email protected]: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2
    

    SO anyone using Go modules will not be able to easily use any newer version of osamingo/jsonrpc.

    Solution

    1. Kill the go.mod files, rolling back to GOPATH.

    This would push them back to not being managed by Go modules (instead of incorrectly using Go modules). Ensure compatibility for downstream module-aware projects and module-unaware projects projects

    2. Fix module path to strictly follow SIV rules.

    Patch the go.mod file to declare the module path as github.com/osamingo/jsonrpc/v2 as per the specs. And adjust all internal imports. The downstream projects might be negatively affected in their building if they are module-unaware (Go versions older than 1.9.7 and 1.10.3; Or use third-party dependency management tools, such as: Dep, glide,govendor…).

    [*] You can see who will be affected here: [1 module-unaware user, i.e., ottenwbe/golook] https://github.com/search?q=osamingo%2Fjsonrpc+filename%3Avendor.conf+filename%3Avendor.json+filename%3Aglide.toml+filename%3AGodep.toml&type=Code&ref=advsearch&l=&l=

    If you don't want to break the above repos. This method can provides better backwards-compatibility. Release a v2 or higher module through the major subdirectory strategy: Create a new v2 subdirectory (github.com/osamingo/jsonrpc/v2) and place a new go.mod file in that subdirectory. The module path must end with /v2. Copy or move the code into the v2 subdirectory. Update import statements within the module to also use /v2 (import "github.com/osamingo/jsonrpc/v2/…"). Tag the release with v2.x.y.

    3. Suggest your downstream module users use hash instead of a version tag.

    If the standard rule of go modules conflicts with your development mode. Or not intended to be used as a library and does not make any guarantees about the API. So you can’t comply with the specification of "Releasing Modules for v2 or higher" available in the Modules documentation. Regardless, since it's against one of the design choices of Go, it'll be a bit of a hack. Instead of go get github.com/osamingo/jsonrpc@version-tag, module users need to use this following way to get the osamingo/jsonrpc: (1) Search for the tag you want (in browser) (2) Get the commit hash for the tag you want (3) Run go get github.com/osamingo/jsonrpc@commit-hash (4) Edit the go.mod file to put a comment about which version you actually used This will make it difficult for module users to get and upgrade osamingo/jsonrpc.

    [*] You can see who will be affected here: [7 module users, e.g., goodgophers goodgophers/golsp-sdk, podhmo/individual-sandbox, xhebox/chrootd…] https://github.com/search?q=osamingo%2Fjsonrpc+filename%3Ago.mod&type=Code&ref=advsearch&l=&l=

    Summary

    You can make a choice to fix DM issues by balancing your own development schedules/mode against the affects on the downstream projects.

    For this issue, Solution 2 can maximize your benefits and with minimal impacts to your downstream projects the ecosystem.

    References

    • https://github.com/golang/go/wiki/Modules#semantic-import-versioning
    • https://golang.org/cmd/go/#hdr-Module_compatibility_and_semantic_versioning
    • https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher
  • add jsonrpc method metadata to context

    add jsonrpc method metadata to context

    WHAT

    • Write the change being made with this pull request. add jsonrpc Metadata to context

    WHY

    • Write the motivation why you submit this pull request. I need it in my project and I thin it can be useful for all. And I see no harm from this. Metadata in context allows to know jsonrpc method name for common logging, or 'params' allows unmarhal parameter as a common step of handling. All this benefits when there is multiple-layer handling of jsonrpc request in complex api`s
  • Error message lost if ServeJSONRPC result Marshal fail

    Error message lost if ServeJSONRPC result Marshal fail

    Here error message is lost: https://github.com/osamingo/jsonrpc/blob/7ed99b3168076a487e397719087198908fc1e4d8/handler.go#L38

    This message is critical for developer to find reason of fail

  • Update package name due to #43

    Update package name due to #43

    WHAT

    Updated module name to /v2 according to last tag

    WHY

    Motivation is greatly described in #43

    Additional actions

    After merging should add new tag (e.g. "v2.3.1") for the module to begin be usable

  • Add request metadata to context (try #2)

    Add request metadata to context (try #2)

    WHAT

    See header

    WHY

    Metadata in context allows params unmarshalling as a general step for processing jsonrpc request

    First my try to mege this PR was failed because of some git-and-rebase-related problems. This is second try

  • Add HandlerFunc implementation

    Add HandlerFunc implementation

    a small step to middleware implementation

    WHAT

    Full analog of golang`s http.HandlerFunc for jsonrpc handlers

    WHY

    something like syntax sugar. Allows to all practices developed for http.Handler be usable for jsonrpc.Handler

  • How to log RPC requests properly?

    How to log RPC requests properly?

    So far I've implemented a logger call inside each handler, which doesn't look like the best idea.

    I think the best place to log requests is right after the parser, so it's really nice to have some kind of middleware support.

    Probably somewhere in here?

    https://github.com/osamingo/jsonrpc/blob/352acaa9f2b2e31b960ce10950aaa396213b9505/handler.go#L45-L53

Simple, fast and scalable golang rpc library for high load

gorpc Simple, fast and scalable golang RPC library for high load and microservices. Gorpc provides the following features useful for highly loaded pro

Dec 19, 2022
The Go language implementation of gRPC. HTTP/2 based RPC

gRPC-Go The Go implementation of gRPC: A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information

Jan 7, 2023
Hprose is a cross-language RPC. This project is Hprose for Golang.
Hprose is a cross-language RPC. This project is Hprose for Golang.

Hprose 3.0 for Golang Introduction Hprose is a High Performance Remote Object Service Engine. It is a modern, lightweight, cross-language, cross-platf

Dec 26, 2022
A Go library for master-less peer-to-peer autodiscovery and RPC between HTTP services

sleuth sleuth is a Go library that provides master-less peer-to-peer autodiscovery and RPC between HTTP services that reside on the same network. It w

Dec 28, 2022
Distributed Lab 2: RPC in Go

Distributed Lab 2: RPC in Go Using the lab sheet There are two ways to use the lab sheet, you can either: create a new repo from this template - this

Oct 18, 2021
Flowgraph package for scalable asynchronous system development

flowgraph Getting Started go get -u github.com/vectaport/flowgraph go test Links Wiki Slides from Minneapolis Golang Meetup, May 22nd 2019 Overview F

Dec 22, 2022
Full-featured BitTorrent client package and utilities

torrent This repository implements BitTorrent-related packages and command-line utilities in Go. The emphasis is on use as a library from other projec

Jan 4, 2023
this is a funny client for jsonrpc-client. it can support timeout,breaker ...

this is a funny client for jsonrpc-client. it can support timeout,breaker ...

Sep 17, 2022
rpc/v2 support for JSON-RPC 2.0 Specification.

rpc rpc/v2 support for JSON-RPC 2.0 Specification. gorilla/rpc is a foundation for RPC over HTTP services, providing access to the exported methods of

Jul 4, 2021
others implement usefuls stuff in their free time. I implement an eventstore framework

Eventstore eventstore is a library where I try out new stuff related to an eventstore as a single point of truth. At the moment I'm writing this it's

Nov 10, 2022
vjson is a Go package that helps to validate JSON objects in a declarative way.

vjson vjson is a Go package that helps to validate JSON objects in a declarative way. Getting Started Installing For installing vjson, use command bel

Nov 24, 2022
Cap'n Proto library and parser for go. This is go-capnproto-1.0, and does not have rpc. See https://github.com/zombiezen/go-capnproto2 for 2.0 which has rpc and capabilities.

Version 1.0 vs 2.0 Update 2015 Sept 20: Big news! Version 2.0 of the go-bindings, authored by Ross Light, is now released and newly available! It feat

Nov 29, 2022
RPC explained by writing simple RPC framework in 300 lines of pure Golang.

Simple GoRPC Learning RPC basic building blocks by building a simple RPC framework in Golang from scratch. RPC In Simple Term Service A wants to call

Dec 17, 2022
Antenna RPC is an RPC protocol for distributed computing, it's based on QUIC and Colfer. its currently an WIP.

aRPC - Antenna Remote Procedure Call Antenna remote procedure call (aRPC) is an RPC protocol focused on distributed processing and HPC. aRPC is implem

Jun 16, 2021
Go Substrate RPC Client (GSRPC)Go Substrate RPC Client (GSRPC)

Go Substrate RPC Client (GSRPC) Substrate RPC client in Go. It provides APIs and types around Polkadot and any Substrate-based chain RPC calls. This c

Nov 11, 2021
RPC Framework abstraction layer. Provides foundation of the RonyDesc to generate RPC server/client codes.

RonyKit RonyKit provides the abstraction layer for creating a cluster aware API server. By defining separate components for each task, you are almost

Dec 15, 2022
A simple go implementation of json rpc 2.0 client over http

JSON-RPC 2.0 Client for golang A go implementation of an rpc client using json as data format over http. The implementation is based on the JSON-RPC 2

Dec 15, 2022
Generate TypeScript interfaces from Go structs/interfaces - useful for JSON RPC

bel Generate TypeScript interfaces from Go structs/interfaces - useful for JSON RPC bel is used in production in https://gitpod.io. Getting started be

Oct 23, 2022
idiomatic codec and rpc lib for msgpack, cbor, json, etc. msgpack.org[Go]

go-codec This repository contains the go-codec library, the codecgen tool and benchmarks for comparing against other libraries. This is a High Perform

Dec 19, 2022
Golang client for ethereum json rpc api

Ethrpc Golang client for ethereum JSON RPC API. web3_clientVersion web3_sha3 net_version net_peerCount net_listening eth_protocolVersion eth_syncing e

Jan 7, 2023