diff --git a/client/http_client.go b/client/http_client.go index 3eb35aa3c..960869b75 100644 --- a/client/http_client.go +++ b/client/http_client.go @@ -67,11 +67,16 @@ func NewClientJSONRPC(remote string) *ClientJSONRPC { } func (c *ClientJSONRPC) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) { - // Make request and get responseBytes + // we need this step because we attempt to decode values using `go-wire` + // (handlers.go:176) on the server side + encodedParams := make(map[string]interface{}) + for k, v := range params { + encodedParams[k] = json.RawMessage(wire.JSONBytes(v)) + } request := types.RPCRequest{ JSONRPC: "2.0", Method: method, - Params: params, + Params: encodedParams, ID: "", } requestBytes, err := json.Marshal(request) diff --git a/rpc_test.go b/rpc_test.go index 990122517..a719aee55 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -1,6 +1,9 @@ package rpc import ( + "bytes" + crand "crypto/rand" + "math/rand" "net/http" "os/exec" "testing" @@ -29,14 +32,20 @@ type ResultStatus struct { Value string } +type ResultBytes struct { + Value []byte +} + var _ = wire.RegisterInterface( struct{ Result }{}, wire.ConcreteType{&ResultStatus{}, 0x1}, + wire.ConcreteType{&ResultBytes{}, 0x2}, ) // Define some routes var Routes = map[string]*server.RPCFunc{ "status": server.NewRPCFunc(StatusResult, "arg"), + "bytes": server.NewRPCFunc(BytesResult, "arg"), } // an rpc function @@ -44,6 +53,10 @@ func StatusResult(v string) (Result, error) { return &ResultStatus{v}, nil } +func BytesResult(v []byte) (Result, error) { + return &ResultBytes{v}, nil +} + // launch unix and tcp servers func init() { cmd := exec.Command("rm", "-f", unixSocket) @@ -214,3 +227,31 @@ func TestQuotedStringArg(t *testing.T) { t.Fatalf("Got: %v .... Expected: %v \n", got, val) } } + +func randBytes(t *testing.T) []byte { + n := rand.Intn(10) + 2 + buf := make([]byte, n) + _, err := crand.Read(buf) + if err != nil { + t.Fatal(err) + } + return bytes.Replace(buf, []byte("="), []byte{100}, -1) +} + +func TestByteSliceViaJSONRPC(t *testing.T) { + cl := client.NewClientJSONRPC(unixAddr) + + val := randBytes(t) + params := map[string]interface{}{ + "arg": val, + } + var result Result + _, err := cl.Call("bytes", params, &result) + if err != nil { + t.Fatal(err) + } + got := result.(*ResultBytes).Value + if bytes.Compare(got, val) != 0 { + t.Fatalf("Got: %v .... Expected: %v \n", got, val) + } +}