jrpc2server

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 18, 2018 License: MIT Imports: 11 Imported by: 0

README

jrpc2server (early beta)

Website | Contributing

license GoDoc Coverage Status Build Status Go Report Card

Golang package for easy creation JSON-RPC 2.0 API services.

System requirements

  • github.com/valyala/fasthttp
  • github.com/riftbit/jrpc2errors
  • tested on golang 1.10.1+

Examples

Benchmark results

Tested on work PC (4 cores, 16gb memory, windows 10)

Used memory on all benchmark time: 7.2 MB

Used CPU on all benchmark time: 12%

Load soft used on same PC: SuperBenchmark (sb)

Benchmark Results

Without routing
package main

import (
	"github.com/valyala/fasthttp"
	"github.com/riftbit/jrpc2server"
	"log"
	"runtime"
	"runtime/debug"
)

//Log area
type DemoAPI struct{}

//Add Method to add Log
func (h *DemoAPI) Test(ctx *fasthttp.RequestCtx, args *struct{ID string}, reply *struct{LogID string}) error {
	//log.Println(args)
	reply.LogID = args.ID
	return nil
}

func main() {
	api := jrpc2server.NewServer()
	err := api.RegisterService(new(DemoAPI), "demo")

	if err != nil {
		log.Fatalln(err)
	}

	fasthttp.ListenAndServe(":8081", api.APIHandler)
}
With minimal routing
package main

import (
	"github.com/valyala/fasthttp"
	"github.com/riftbit/jrpc2server"
	"log"
	"runtime"
	"runtime/debug"
)

//Log area
type DemoAPI struct{}

//Add Method to add Log
func (h *DemoAPI) Test(ctx *fasthttp.RequestCtx, args *struct{ID string}, reply *struct{LogID string}) error {
	//log.Println(args)
	reply.LogID = args.ID
	return nil
}

func main() {
	api := jrpc2server.NewServer()
	err := api.RegisterService(new(DemoAPI), "demo")

	if err != nil {
		log.Fatalln(err)
	}

	reqHandler := func(ctx *fasthttp.RequestCtx) {
		switch string(ctx.Path()) {
		case "/api":
			api.APIHandler(ctx)
		default:
			ctx.Error("Unsupported path", fasthttp.StatusNotFound)
		}
	}

	fasthttp.ListenAndServe(":8081", reqHandler)
}
With advanced routing and middlewares (not tested, will be updated)
package main

import (
	"github.com/valyala/fasthttp"
	"github.com/riftbit/jrpc2server"
	"github.com/thehowl/fasthttprouter"
	"log"
	"runtime"
	"runtime/debug"
)

//Log area
type DemoAPI struct{}

//Add Method to add Log
func (h *DemoAPI) Test(ctx *fasthttp.RequestCtx, args *struct{ID string}, reply *struct{LogID string}) error {
	//log.Println(args)
	reply.LogID = args.ID
	return nil
}


func main() {
	api := jrpc2server.NewServer()
	err := api.RegisterService(new(DemoAPI), "demo")
	if err != nil {
		log.Fatalln(err)
	}

	router := fasthttprouter.New()
    router.POST("/", mainHandler())

	server := fasthttp.Server{
		Name:    "AWESOME SERVER BY RIFTBIT.COM",
		Handler: router.Handler,
	}

	Logger.Println("Started fasthttp server on port", config.System.ListenOn)
	Logger.Fatal(server.ListenAndServe(config.System.ListenOn))
}


func mainHandler() fasthttp.RequestHandler {
	return fasthttp.RequestHandler(func(ctx *fasthttp.RequestCtx) {
		stats := statsData{EventTime: time.Now()}

        //Here you can run any handlers you need
		API.APIHandler(ctx)

		ctx.Response.Header.Set("Server", ServerName)
		ctx.Response.Header.Set("X-Powered-By", PoweredBy+build)

		stats.UsedTime = time.Since(stats.EventTime)
		stats.ClientIP = ctx.RemoteIP().String()

		ctx.Request.Header.VisitAll(func(key, value []byte) {
			if string(key) == "X-Forwarded-For" {
				stats.ClientIP = string(value)
			}
		})

		stats.StatusCode = ctx.Response.StatusCode()
		stats.Host = ctx.Request.Host()
		stats.UserAgent = ctx.Request.Header.UserAgent()

		stats.BodyReq = ctx.Request.Body()
		stats.BodyResp = ctx.Response.Body()

        /*
        do something with stats :)
        *./

		return
	})
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Version = "2.0"

Version is JSON RPC version that allowed to use

Functions

func PrepareDataHandler

func PrepareDataHandler(ctx *fasthttp.RequestCtx)

PrepareDataHandler process basic data to context values PrepareDataHandlerRequestErr.(error) and PrepareDataHandlerRequest.(*ServerRequest) and PrepareDataHandlerRequestRun.(int)

func ReadRequestParams

func ReadRequestParams(request *ServerRequest, args interface{}) error

ReadRequestParams getting request parametrs

func WriteResponse

func WriteResponse(ctx *fasthttp.RequestCtx, status int, resp *ServerResponse)

WriteResponse write response to client with status code and server response struct

Types

type APIServer

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

APIServer - main structure

func NewServer

func NewServer() *APIServer

NewServer returns a new RPC server.

func (*APIServer) APIHandler

func (as *APIServer) APIHandler(ctx *fasthttp.RequestCtx)

APIHandler handle api request, process it and return result

func (*APIServer) GetAllServices

func (as *APIServer) GetAllServices() (map[string]*Service, error)

GetAllServices returns an all registered services

The method name uses a dotted notation as in "Service.Method".

func (*APIServer) RegisterService

func (as *APIServer) RegisterService(receiver interface{}, name string) error

RegisterService adds a new service to the server.

The name parameter is optional: if empty it will be inferred from the receiver type name.

Methods from the receiver will be extracted if these rules are satisfied:

  • The receiver is exported (begins with an upper case letter) or local (defined in the package registering the service).
  • The method name is exported.
  • The method has three arguments: *http.Request, *args, *reply.
  • All three arguments are pointers.
  • The second and third arguments are exported or local.
  • The method has return type error.

All other methods are ignored.

type EmptyResponse

type EmptyResponse struct{}

EmptyResponse empty response

type ServerRequest

type ServerRequest struct {
	// JSON-RPC protocol.
	Version string `json:"jsonrpc"`

	// A String containing the name of the method to be invoked.
	Method string `json:"method"`

	// A Structured value to pass as arguments to the method.
	Params *json.RawMessage `json:"params"`

	// The request id. MUST be a string, number or null.
	// Our implementation will not do type checking for id.
	// It will be copied as it is.
	ID *json.RawMessage `json:"id"`
}

ServerRequest represents a JSON-RPC request received by the server.

type ServerResponse

type ServerResponse struct {
	// JSON-RPC protocol.
	Version string `json:"jsonrpc"`

	// The Object that was returned by the invoked method. This must be null
	// in case there was an error invoking the method.
	// As per spec the member will be omitted if there was an error.
	Result interface{} `json:"result,omitempty"`

	// An Error object if there was an error invoking the method. It must be
	// null if there was no error.
	// As per spec the member will be omitted if there was no error.
	Error *jrpc2errors.Error `json:"error,omitempty"`

	// This must be the same id as the request it is responding to.
	ID *json.RawMessage `json:"id"`
}

ServerResponse represents a JSON-RPC response returned by the server.

type Service

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

Service - sub struct

type ServiceMap

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

ServiceMap is a registry for services.

type ServiceMethod

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

ServiceMethod - sub struct

Jump to

Keyboard shortcuts

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