From d6fd0c4ca07c0be6d6503d5231060301a3494ab1 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 21 Apr 2017 18:30:22 +0300 Subject: [PATCH 1/2] fix backward compatibility for WS --- rpc_test.go | 28 ++++++++++++++++++++++++++++ server/handlers.go | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/rpc_test.go b/rpc_test.go index 56b8ade32..ed28cbc8d 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -261,6 +261,34 @@ func TestWSNewWSRPCFunc(t *testing.T) { } } +func TestWSHandlesArrayParams(t *testing.T) { + cl := client.NewWSClient(tcpAddr, websocketEndpoint) + _, err := cl.Start() + require.Nil(t, err) + defer cl.Stop() + + val := "acbd" + params := []interface{}{val} + err = cl.WriteJSON(types.RPCRequest{ + JSONRPC: "2.0", + ID: "", + Method: "echo_ws", + Params: params, + }) + require.Nil(t, err) + + select { + case msg := <-cl.ResultsCh: + result := new(Result) + wire.ReadJSONPtr(result, msg, &err) + require.Nil(t, err) + got := (*result).(*ResultEcho).Value + assert.Equal(t, got, val) + case err := <-cl.ErrorsCh: + t.Fatalf("%+v", err) + } +} + func randBytes(t *testing.T) []byte { n := rand.Intn(10) + 2 buf := make([]byte, n) diff --git a/server/handlers.go b/server/handlers.go index de2b8094f..9fa327cbb 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -173,7 +173,7 @@ func jsonParamsToArgs(rpcFunc *RPCFunc, paramsI interface{}, argsOffset int) ([] } values := make([]reflect.Value, len(params)) for i, p := range params { - ty := rpcFunc.args[i] + ty := rpcFunc.args[i+argsOffset] v, err := _jsonObjectToArg(ty, p) if err != nil { return nil, err From a01cff9ce630a93168ff7aa003072a7164bdc1ef Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 12:18:21 -0400 Subject: [PATCH 2/2] jsonParamsToArgsRPC func --- server/handlers.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/server/handlers.go b/server/handlers.go index 9fa327cbb..9be64b775 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -124,7 +124,7 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc { WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, nil, "RPC method is only for websockets: "+request.Method)) return } - args, err := jsonParamsToArgs(rpcFunc, request.Params, 0) + args, err := jsonParamsToArgsRPC(rpcFunc, request.Params) if err != nil { WriteRPCResponseHTTP(w, types.NewRPCResponse(request.ID, nil, fmt.Sprintf("Error converting json params to arguments: %v", err.Error()))) return @@ -142,7 +142,7 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc { // Convert a []interface{} OR a map[string]interface{} to properly typed values // -// argsOffset is used in jsonParamsToArgsWS, where len(rpcFunc.args) != len(rpcFunc.argNames). +// argsOffset should be 0 for RPC calls, and 1 for WS requests, where len(rpcFunc.args) != len(rpcFunc.argNames). // Example: // rpcFunc.args = [rpctypes.WSRPCContext string] // rpcFunc.argNames = ["arg"] @@ -187,6 +187,11 @@ func jsonParamsToArgs(rpcFunc *RPCFunc, paramsI interface{}, argsOffset int) ([] return values, nil } +// Convert a []interface{} OR a map[string]interface{} to properly typed values +func jsonParamsToArgsRPC(rpcFunc *RPCFunc, paramsI interface{}) ([]reflect.Value, error) { + return jsonParamsToArgs(rpcFunc, paramsI, 0) +} + // Same as above, but with the first param the websocket connection func jsonParamsToArgsWS(rpcFunc *RPCFunc, paramsI interface{}, wsCtx types.WSRPCContext) ([]reflect.Value, error) { values, err := jsonParamsToArgs(rpcFunc, paramsI, 1) @@ -494,7 +499,7 @@ func (wsc *wsConnection) readRoutine() { wsCtx := types.WSRPCContext{Request: request, WSRPCConnection: wsc} args, err = jsonParamsToArgsWS(rpcFunc, request.Params, wsCtx) } else { - args, err = jsonParamsToArgs(rpcFunc, request.Params, 0) + args, err = jsonParamsToArgsRPC(rpcFunc, request.Params) } if err != nil { wsc.WriteRPCResponse(types.NewRPCResponse(request.ID, nil, err.Error()))