Giter VIP home page Giter VIP logo

rpc-codec's People

Contributors

anpryl avatar powerman avatar trey-jones avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rpc-codec's Issues

Add example how to use WebSocket with JSON-RPC 2.0

I'm running jsonrpc2 with custom ReadWriteCloser becuase the underlying connection is Websocket.

s.ServeCodec(jsonrpc2.NewServerCodec(rwc, nil))

If you look at the go/src/encoding/json/stream.go:144 (refill method), the default slice size is "const minRead = 512"
So, the stream calls my Read() method by asking for exactly 512 bytes. If I have a json message with exactly that size then the Read() returns n=512 and err=nil
Then the stream calls Read() again, by asking again for new 512 bytes. Since there is no data to return, the method returns n=0, and err=io.EOF which is what is expected by the Reader interface.

Unfortunately that produces "empty" string/json, so that propagates back to ReadRequestHeader method ( go/src/github.com/powerman/rpc-codec/jsonrpc2/server.go ),which cause errParse and shutdown of the RPC handler/current websocket connection.

The only workaround in my Read() is to return the second time n=0, err=nil which is "discouraged" according to the documentation.

Custom field in Call

Hello,
I'm using your rpc-codec library in order to create a wrapper from Zabbix' API.

https://zabbix.com/documentation/4.0/manual/api

In their documentation they use a custom field "Auth" containing a token obtained after the login. How can I make a call with customs field like this?

{ "jsonrpc": "2.0", "method": "host.get", "params": { "output": [ "hostid", "host" ], "selectInterfaces": [ "interfaceid", "ip" ] }, "id": 2, "auth": "0424bd59b807674191e7d77572075f33" }

measure runtime by method

Hi all,

i would like to measure the runtimes each call is taking and group it by the jsonrpc method using the following code:

func handleRequest(ctx context.Context, rc io.ReadCloser) bytes.Buffer {
	var res bytes.Buffer

	codec := jsonrpc2.NewServerCodecContext(ctx, struct {
		io.ReadCloser
		io.Writer
	}{
		rc,
		&res,
	}, nil)

	err := rpc.ServeRequest(codec)
	if err != nil {
		log.WithError(err).Error("rpc.ServeRequest")
	}

	fmt.Printf("%+v\n", codec)

	return res
}

the data i am looking for is already in the "codec" variable after rpc.ServeRequest:

&{encmutex:{state:0 sema:0} dec:0xc00157fce0 enc:0xc004b47540 c:{ReadCloser:{Reader:0xc00137b8c0} Writer:0xc00137b8f0} srv:0xc0000ec140 ctx:0xc00137b7d0 req:{Version:2.0 Method:System.Hello Params:0xc0053867e0 ID:} mutex:{state:0 sema:0} seq:1 pending:map[]

but i am unable to access it due to "req" not being exported.

Is there really no other way but to decode the json a second time just to get the method name?

Many thanks in advance!

Content-Type and Accept

As mentioned in JSON-RPC over HTTP specification Content-Type SHOULD be application/json-rpc but MAY be application/json or application/jsonrequest and The Accept MUST be specified and SHOULD read application/json-rpc but MAY be application/json or application/jsonrequest. Is there any chance for supporting this specification in http.go?

Positional args in server

I have this code:

package main

import (
	"io"
	"net"
	"net/http"
	"net/rpc"

	"github.com/powerman/rpc-codec/jsonrpc2"
)

type HttpConn struct {
	in  io.Reader
	out io.Writer
}

func (c *HttpConn) Read(p []byte) (n int, err error)  {
	return c.in.Read(p)
}

func (c *HttpConn) Write(d []byte) (n int, err error) {
	return c.out.Write(d)
}

func (c *HttpConn) Close() error {
	return nil
}

type Test struct{}

type TestHelloArgs struct {
	Name string
}

var server *rpc.Server

func (test *Test) Hello(args *TestHelloArgs, result *string) error {
	*result = "Hello " + args.Name
	return nil
}

func main() {

	server = rpc.NewServer()
	_ = server.Register(&Test{})

	listener, err := net.Listen("tcp", ":8080")

	if err != nil {
		panic(err)
	}

	_ = http.Serve(listener, http.HandlerFunc(handler))
}

func handler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/rpc" {
		serverCodec := jsonrpc2.NewServerCodec(&HttpConn{in: r.Body, out: w}, server )

		w.Header().Set( "Content-type", "application/json" )
		w.WriteHeader(200)

		if err1 := server.ServeRequest(serverCodec) ; err1 != nil {
			http.Error(w, "Error while serving JSON request", 500)
			return
		}
	} else {
		http.Error(w, "Unknown request", 404)
	}
}

I send HTTP-request:

POST http://localhost:8080/rpc
Content-Type: application/json

[
  {
    "jsonrpc": "2.0",
    "method": "Test.Hello",
    "params": {
      "Name": "R1"
    },
    "id": "a"
  },
  {
    "jsonrpc": "2.0",
    "method": "Test.Hello",
    "params": [
      "R2"
    ],
    "id": "z"
  }
]

... and response:

HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 26 Jun 2019 10:45:41 GMT
Content-Length: 122

[
  {
    "jsonrpc": "2.0",
    "id": "a",
    "result": "Hello R1"
  },
  {
    "jsonrpc": "2.0",
    "id": "z",
    "error": {
      "code": -32602,
      "message": "bad request"
    }
  }
]

How to make it so that I can use both named and positional parameters

Reponse object is not implemented correctly.

The response returned by this package always contains a result and error attribute. According to the specification those attributes are mutually exclusive:

Response Object

...

result
This member is REQUIRED on success.
This member MUST NOT exist if there was an error invoking the method.
The value of this member is determined by the method invoked on the Server.

error
This member is REQUIRED on error.
This member MUST NOT exist if there was no error triggered during invocation.
The value for this member MUST be an Object as defined in section 5.1.

example to use tcp as transport

Hi,

Is there an example where we use tcp as transport and have the params as json (encoded) string.
The below code gives me
error:invalid character 'C' looking for beginning of value exit status 1

package main

import (
	"encoding/json"
	"log"
	"net"
	"net/rpc/jsonrpc" 
        "github.com/powerman/rpc-codec"
)

var params interface{}

func main() {

	conn, err := net.Dial("tcp", "localhost:7777") // works fine

	if err != nil {
		panic(err)
	}
	defer conn.Close()

	con := jsonrpc.NewClient(conn)

	var paramsJSON string
	paramsJSON = `` //`{"namedArg1":"value"}`
	err = json.Unmarshal([]byte(paramsJSON), &params)
	var result interface{}
	err1 := con.Call("help", params, &result)
	if err1 != nil {
		log.Fatal("error:", err1)
	}
	log.Printf("%v", reply)
}

Support for method name mapping

I'm converting a legacy system from Python into Go, and I have some restrictions on the method names that don't work with Go's RPC layer and rpc-codec. The legacy method names are all lowercase and do not have a namespace structure "namespace.method". rpc-codec works great for me with a small hack to add "default." and capitalize the first letter of the method name. Is there an interest in making this part of rpc-codec. If desired, I could change this to a more generic "method transform" callback.

see:

tdterry@a61f131

Middleware support

Does the project have the support of middlewares?
So if not - I can implement it.
Now I can just wrap around ServeHTTP function, but sometimes I wanna choose a group to wrap it.

Memory leaks: no data in channel

Line 117 makes connection goroutine stuck.

rpc-codec/jsonrpc2/http.go

Lines 107 to 121 in f48fde4

func (conn *httpClientConn) Read(buf []byte) (int, error) {
if conn.body == nil {
conn.body = <-conn.ready
}
n, err := conn.body.Read(buf)
if err == io.EOF {
conn.body.Close()
conn.body = nil
err = nil
if n == 0 {
return conn.Read(buf)
}
}
return n, err
}

So after a couple of hours we have 2Gb of memory allocated. And it keeps growing.

I don't know how to fix it (don't even know where the real bug is) but we made a workaround:

func (conn *httpClientConn) Read(buf []byte) (int, error) { 
	if conn.body == nil { 
		select {
		case conn.body = <-conn.ready:
		case <-time.After(time.Second * 30):
			return 0, io.EOF
		}
	}

...

}

Not a smart one but at least it stopped growing as fast as hell.

Bug: Builtin type can not send as params direct.

When i send Builtin type as params direct.
It report errors like this.

arith error:{"code":-32603,"message":"unsupported param type: string"}
arith error:{"code":-32603,"message":"unsupported param type: int"}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.