From 2dc6ab3896e876d7ec2371b3faa6112971e9e849 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 8 Mar 2017 17:16:01 +0400 Subject: [PATCH] use golang default if an arg is missing (Refs #7) --- server/handlers.go | 54 +++++++++++++++++++++++----------------- test/integration_test.sh | 19 +++++++++++++- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/server/handlers.go b/server/handlers.go index beb664d9f..7085b81e2 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -141,20 +141,20 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc { // Convert a list of interfaces to properly typed values func jsonParamsToArgs(rpcFunc *RPCFunc, params map[string]interface{}) ([]reflect.Value, error) { - if len(rpcFunc.argNames) != len(params) { - return nil, fmt.Errorf("Expected %v parameters (%v), got %v (%v)", - len(rpcFunc.argNames), rpcFunc.argNames, len(params), params) - } + values := make([]reflect.Value, len(rpcFunc.args)) - values := make([]reflect.Value, len(params)) + // fill each value with default + for i, argType := range rpcFunc.args { + values[i] = reflect.Zero(argType) + } for name, param := range params { i := indexOf(name, rpcFunc.argNames) if -1 == i { return nil, fmt.Errorf("%s is not an argument (args: %v)", name, rpcFunc.argNames) } - ty := rpcFunc.args[i] - v, err := _jsonObjectToArg(ty, param) + argType := rpcFunc.args[i] + v, err := _jsonObjectToArg(argType, param) if err != nil { return nil, err } @@ -176,21 +176,21 @@ func indexOf(value string, values []string) int { // Same as above, but with the first param the websocket connection func jsonParamsToArgsWS(rpcFunc *RPCFunc, params map[string]interface{}, wsCtx types.WSRPCContext) ([]reflect.Value, error) { - if len(rpcFunc.argNames) != len(params) { - return nil, fmt.Errorf("Expected %v parameters (%v), got %v (%v)", - len(rpcFunc.argNames)-1, rpcFunc.argNames[1:], len(params), params) - } - - values := make([]reflect.Value, len(params)+1) + values := make([]reflect.Value, len(rpcFunc.args)) values[0] = reflect.ValueOf(wsCtx) + // fill each value with default + for i, argType := range rpcFunc.args { + values[i+1] = reflect.Zero(argType) + } + for name, param := range params { i := indexOf(name, rpcFunc.argNames) if -1 == i { return nil, fmt.Errorf("%s is not an argument (args: %v)", name, rpcFunc.argNames) } - ty := rpcFunc.args[i+1] - v, err := _jsonObjectToArg(ty, param) + argType := rpcFunc.args[i+1] + v, err := _jsonObjectToArg(argType, param) if err != nil { return nil, err } @@ -245,16 +245,23 @@ func makeHTTPHandler(rpcFunc *RPCFunc) func(http.ResponseWriter, *http.Request) // Covert an http query to a list of properly typed values. // To be properly decoded the arg must be a concrete type from tendermint (if its an interface). func httpParamsToArgs(rpcFunc *RPCFunc, r *http.Request) ([]reflect.Value, error) { - argTypes := rpcFunc.args - argNames := rpcFunc.argNames + values := make([]reflect.Value, len(rpcFunc.args)) - values := make([]reflect.Value, len(argNames)) - for i, name := range argNames { - ty := argTypes[i] + // fill each value with default + for i, argType := range rpcFunc.args { + values[i] = reflect.Zero(argType) + } + + for i, name := range rpcFunc.argNames { + argType := rpcFunc.args[i] arg := GetParam(r, name) - // log.Notice("param to arg", "ty", ty, "name", name, "arg", arg) + // log.Notice("param to arg", "argType", argType, "name", name, "arg", arg) + + if "" == arg { + continue + } - v, err, ok := nonJsonToArg(ty, arg) + v, err, ok := nonJsonToArg(argType, arg) if err != nil { return nil, err } @@ -264,11 +271,12 @@ func httpParamsToArgs(rpcFunc *RPCFunc, r *http.Request) ([]reflect.Value, error } // Pass values to go-wire - values[i], err = _jsonStringToArg(ty, arg) + values[i], err = _jsonStringToArg(argType, arg) if err != nil { return nil, err } } + return values, nil } diff --git a/test/integration_test.sh b/test/integration_test.sh index 5c85704be..ea246c896 100755 --- a/test/integration_test.sh +++ b/test/integration_test.sh @@ -28,6 +28,7 @@ if [[ "$R1" != "$R2" ]]; then echo "responses are not identical:" echo "R1: $R1" echo "R2: $R2" + echo "FAIL" exit 1 else echo "OK" @@ -40,18 +41,33 @@ if [[ "$R1" != "$R2" ]]; then echo "responses are not identical:" echo "R1: $R1" echo "R2: $R2" + echo "FAIL" exit 1 else echo "OK" fi -# request with unquoted string arg +echo "==> request with missing params" +R1=$(curl -s 'http://localhost:8008/hello_world') +R2='{"jsonrpc":"2.0","id":"","result":{"Result":"hi 0"},"error":""}' +if [[ "$R1" != "$R2" ]]; then + echo "responses are not identical:" + echo "R1: $R1" + echo "R2: $R2" + echo "FAIL" + exit 1 +else + echo "OK" +fi + +echo "==> request with unquoted string arg" R1=$(curl -s 'http://localhost:8008/hello_world?name=abcd&num=123') R2="{\"jsonrpc\":\"2.0\",\"id\":\"\",\"result\":null,\"error\":\"Error converting http params to args: invalid character 'a' looking for beginning of value\"}" if [[ "$R1" != "$R2" ]]; then echo "responses are not identical:" echo "R1: $R1" echo "R2: $R2" + echo "FAIL" exit 1 else echo "OK" @@ -64,6 +80,7 @@ if [[ "$R1" != "$R2" ]]; then echo "responses are not identical:" echo "R1: $R1" echo "R2: $R2" + echo "FAIL" exit 1 else echo "OK"