Browse Source

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
pull/456/head
Matt Bell 8 years ago
parent
commit
34a806578a
4 changed files with 109 additions and 8 deletions
  1. +18
    -1
      client/http_client.go
  2. +36
    -0
      rpc_test.go
  3. +30
    -1
      server/handlers.go
  4. +25
    -6
      test/test.sh

+ 18
- 1
client/http_client.go View File

@ -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
- 0
rpc_test.go View File

@ -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)
}
}

+ 30
- 1
server/handlers.go View File

@ -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


+ 25
- 6
test/test.sh View File

@ -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`
if [[ "$R1" != "$R2" ]]; then
echo "responses are not identical:"
echo "R1: $R1"
echo "R2: $R2"
else
echo "Success"
fi
kill -9 $PID
# 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"
exit 1
else
echo "Success"
fi
echo "Success"
kill -9 $PID

Loading…
Cancel
Save