commit
b494cc5219
|
@ -4,10 +4,12 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
. "github.com/tendermint/go-common"
|
||||
|
@ -119,7 +121,7 @@ func (c *ClientURI) call(method string, params map[string]interface{}, result in
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//log.Info(Fmt("URI request to %v (%v): %v", c.address, method, values))
|
||||
// log.Info(Fmt("URI request to %v (%v): %v", c.address, method, values))
|
||||
resp, err := c.client.PostForm(c.address+"/"+method, values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -176,6 +178,14 @@ func argsToJson(args map[string]interface{}) error {
|
|||
var n int
|
||||
var err error
|
||||
for k, v := range args {
|
||||
// Convert byte slices to "0x"-prefixed hex
|
||||
byteSlice, isByteSlice := reflect.ValueOf(v).Interface().([]byte)
|
||||
if isByteSlice {
|
||||
args[k] = fmt.Sprintf("0x%X", byteSlice)
|
||||
continue
|
||||
}
|
||||
|
||||
// Pass everything else to go-wire
|
||||
buf := new(bytes.Buffer)
|
||||
wire.WriteJSON(v, buf, &n, &err)
|
||||
if err != nil {
|
||||
|
|
36
rpc_test.go
36
rpc_test.go
|
@ -164,3 +164,39 @@ func TestWS_UNIX(t *testing.T) {
|
|||
}
|
||||
testWS(t, cl)
|
||||
}
|
||||
|
||||
func TestHexStringArg(t *testing.T) {
|
||||
cl := rpcclient.NewClientURI(tcpAddr)
|
||||
// should NOT be handled as hex
|
||||
val := "0xabc"
|
||||
params := map[string]interface{}{
|
||||
"arg": val,
|
||||
}
|
||||
var result Result
|
||||
_, err := cl.Call("status", params, &result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := result.(*ResultStatus).Value
|
||||
if got != val {
|
||||
t.Fatalf("Got: %v .... Expected: %v \n", got, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuotedStringArg(t *testing.T) {
|
||||
cl := rpcclient.NewClientURI(tcpAddr)
|
||||
// should NOT be unquoted
|
||||
val := "\"abc\""
|
||||
params := map[string]interface{}{
|
||||
"arg": val,
|
||||
}
|
||||
var result Result
|
||||
_, err := cl.Call("status", params, &result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := result.(*ResultStatus).Value
|
||||
if got != val {
|
||||
t.Fatalf("Got: %v .... Expected: %v \n", got, val)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package rpcserver
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -224,12 +225,22 @@ func httpParamsToArgs(rpcFunc *RPCFunc, r *http.Request) ([]reflect.Value, error
|
|||
argTypes := rpcFunc.args
|
||||
argNames := rpcFunc.argNames
|
||||
|
||||
var err error
|
||||
values := make([]reflect.Value, len(argNames))
|
||||
for i, name := range argNames {
|
||||
ty := argTypes[i]
|
||||
arg := GetParam(r, name)
|
||||
//log.Notice("param to arg", "ty", ty, "name", name, "arg", arg)
|
||||
// log.Notice("param to arg", "ty", ty, "name", name, "arg", arg)
|
||||
|
||||
v, err, ok := nonJsonToArg(ty, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
values[i] = v
|
||||
continue
|
||||
}
|
||||
|
||||
// Pass values to go-wire
|
||||
values[i], err = _jsonStringToArg(ty, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -249,6 +260,44 @@ func _jsonStringToArg(ty reflect.Type, arg string) (reflect.Value, error) {
|
|||
return v, nil
|
||||
}
|
||||
|
||||
func nonJsonToArg(ty reflect.Type, arg string) (reflect.Value, error, bool) {
|
||||
isQuotedString := strings.HasPrefix(arg, `"`) && strings.HasSuffix(arg, `"`)
|
||||
isHexString := strings.HasPrefix(strings.ToLower(arg), "0x")
|
||||
expectingString := ty.Kind() == reflect.String
|
||||
expectingByteSlice := ty.Kind() == reflect.Slice && ty.Elem().Kind() == reflect.Uint8
|
||||
|
||||
if isHexString {
|
||||
if !expectingString && !expectingByteSlice {
|
||||
err := fmt.Errorf("Got a hex string arg, but expected '%s'",
|
||||
ty.Kind().String())
|
||||
return reflect.ValueOf(nil), err, false
|
||||
}
|
||||
|
||||
var value []byte
|
||||
value, err := hex.DecodeString(arg[2:])
|
||||
if err != nil {
|
||||
return reflect.ValueOf(nil), err, false
|
||||
}
|
||||
if ty.Kind() == reflect.String {
|
||||
return reflect.ValueOf(string(value)), nil, true
|
||||
}
|
||||
return reflect.ValueOf([]byte(value)), nil, true
|
||||
}
|
||||
|
||||
if isQuotedString && expectingByteSlice {
|
||||
var err error
|
||||
v := reflect.New(reflect.TypeOf(""))
|
||||
wire.ReadJSONPtr(v.Interface(), []byte(arg), &err)
|
||||
if err != nil {
|
||||
return reflect.ValueOf(nil), err, false
|
||||
}
|
||||
v = v.Elem()
|
||||
return reflect.ValueOf([]byte(v.String())), nil, true
|
||||
}
|
||||
|
||||
return reflect.ValueOf(nil), nil, false
|
||||
}
|
||||
|
||||
// rpc.http
|
||||
//-----------------------------------------------------------------------------
|
||||
// rpc.websocket
|
||||
|
|
|
@ -6,18 +6,52 @@ go build -o server main.go
|
|||
PID=$!
|
||||
sleep 2
|
||||
|
||||
|
||||
# simple request
|
||||
R1=`curl -s 'http://localhost:8008/hello_world?name="my_world"&num=5'`
|
||||
|
||||
|
||||
R2=`curl -s --data @data.json http://localhost:8008`
|
||||
|
||||
kill -9 $PID
|
||||
|
||||
if [[ "$R1" != "$R2" ]]; then
|
||||
echo "responses are not identical:"
|
||||
echo "R1: $R1"
|
||||
echo "R2: $R2"
|
||||
exit 1
|
||||
else
|
||||
echo "Success"
|
||||
fi
|
||||
echo "Success"
|
||||
|
||||
# request with 0x-prefixed hex string arg
|
||||
R1=`curl -s 'http://localhost:8008/hello_world?name=0x41424344&num=123'`
|
||||
R2='{"jsonrpc":"2.0","id":"","result":{"Result":"hi ABCD 123"},"error":""}'
|
||||
if [[ "$R1" != "$R2" ]]; then
|
||||
echo "responses are not identical:"
|
||||
echo "R1: $R1"
|
||||
echo "R2: $R2"
|
||||
exit 1
|
||||
else
|
||||
echo "Success"
|
||||
fi
|
||||
|
||||
# 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"
|
||||
exit 1
|
||||
else
|
||||
echo "Success"
|
||||
fi
|
||||
|
||||
# request with string type when expecting number arg
|
||||
R1=`curl -s 'http://localhost:8008/hello_world?name="abcd"&num=0xabcd'`
|
||||
R2="{\"jsonrpc\":\"2.0\",\"id\":\"\",\"result\":null,\"error\":\"Error converting http params to args: Got a 'hex string' arg, but expected 'int'\"}"
|
||||
if [[ "$R1" != "$R2" ]]; then
|
||||
echo "responses are not identical:"
|
||||
echo "R1: $R1"
|
||||
echo "R2: $R2"
|
||||
exit 1
|
||||
else
|
||||
echo "Success"
|
||||
fi
|
||||
|
||||
kill -9 $PID || exit 0
|
||||
|
|
Loading…
Reference in New Issue