Handle hex strings and quoted strings in HTTP params
Use 0x-prefixed hex strings in client server: Decode hex string args Encode all string args as 0x<hex> without trying to encode as JSON Added tests for special string arguments Fix server handling quoted string args Added string arg handling test cases to bash test script
This commit is contained in:
parent
161e36fd56
commit
34a806578a
|
@ -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,21 @@ func argsToJson(args map[string]interface{}) error {
|
|||
var n int
|
||||
var err error
|
||||
for k, v := range args {
|
||||
// Convert strings to "0x"-prefixed hex
|
||||
str, isString := reflect.ValueOf(v).Interface().(string)
|
||||
if isString {
|
||||
args[k] = fmt.Sprintf("0x%X", str)
|
||||
continue
|
||||
}
|
||||
|
||||
// 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"
|
||||
|
@ -229,7 +230,35 @@ func httpParamsToArgs(rpcFunc *RPCFunc, r *http.Request) ([]reflect.Value, error
|
|||
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)
|
||||
|
||||
// Handle quoted strings
|
||||
if strings.HasPrefix(arg, "\"") && strings.HasSuffix(arg, "\"") {
|
||||
data := arg[1 : len(arg)-1]
|
||||
if ty.Kind() == reflect.String {
|
||||
values[i] = reflect.ValueOf(string(data))
|
||||
} else {
|
||||
values[i] = reflect.ValueOf(data)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Handle hex strings
|
||||
if strings.HasPrefix(strings.ToLower(arg), "0x") {
|
||||
var value []byte
|
||||
value, err = hex.DecodeString(arg[2:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ty.Kind() == reflect.String {
|
||||
values[i] = reflect.ValueOf(string(value))
|
||||
} else {
|
||||
values[i] = reflect.ValueOf(value)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Pass values to go-wire
|
||||
values[i], err = _jsonStringToArg(ty, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -6,18 +6,37 @@ go build -o server main.go
|
|||
PID=$!
|
||||
sleep 2
|
||||
|
||||
|
||||
# simple JSONRPC 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"
|
||||
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"
|
||||
else
|
||||
echo "Success"
|
||||
fi
|
||||
|
||||
kill -9 $PID
|
||||
|
|
Loading…
Reference in New Issue