rpc: improve error messages for invalid arguments
The message now includes the index of the invalid arg.
This commit is contained in:
parent
2be3c4b0e3
commit
a3e3235d97
63
rpc/json.go
63
rpc/json.go
@ -17,6 +17,7 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -266,42 +267,42 @@ func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// parsePositionalArguments tries to parse the given args to an array of values with the given types.
|
// parsePositionalArguments tries to parse the given args to an array of values with the
|
||||||
// It returns the parsed values or an error when the args could not be parsed. Missing optional arguments
|
// given types. It returns the parsed values or an error when the args could not be
|
||||||
// are returned as reflect.Zero values.
|
// parsed. Missing optional arguments are returned as reflect.Zero values.
|
||||||
func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) ([]reflect.Value, Error) {
|
func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]reflect.Value, Error) {
|
||||||
params := make([]interface{}, 0, len(callbackArgs))
|
// Read beginning of the args array.
|
||||||
for _, t := range callbackArgs {
|
dec := json.NewDecoder(bytes.NewReader(rawArgs))
|
||||||
params = append(params, reflect.New(t).Interface())
|
if tok, _ := dec.Token(); tok != json.Delim('[') {
|
||||||
|
return nil, &invalidParamsError{"non-array args"}
|
||||||
}
|
}
|
||||||
|
// Read args.
|
||||||
if err := json.Unmarshal(args, ¶ms); err != nil {
|
args := make([]reflect.Value, 0, len(types))
|
||||||
|
for i := 0; dec.More(); i++ {
|
||||||
|
if i >= len(types) {
|
||||||
|
return nil, &invalidParamsError{fmt.Sprintf("too many arguments, want at most %d", len(types))}
|
||||||
|
}
|
||||||
|
argval := reflect.New(types[i])
|
||||||
|
if err := dec.Decode(argval.Interface()); err != nil {
|
||||||
|
return nil, &invalidParamsError{fmt.Sprintf("invalid argument %d: %v", i, err)}
|
||||||
|
}
|
||||||
|
if argval.IsNil() && types[i].Kind() != reflect.Ptr {
|
||||||
|
return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)}
|
||||||
|
}
|
||||||
|
args = append(args, argval.Elem())
|
||||||
|
}
|
||||||
|
// Read end of args array.
|
||||||
|
if _, err := dec.Token(); err != nil {
|
||||||
return nil, &invalidParamsError{err.Error()}
|
return nil, &invalidParamsError{err.Error()}
|
||||||
}
|
}
|
||||||
|
// Set any missing args to nil.
|
||||||
if len(params) > len(callbackArgs) {
|
for i := len(args); i < len(types); i++ {
|
||||||
return nil, &invalidParamsError{fmt.Sprintf("too many params, want %d got %d", len(callbackArgs), len(params))}
|
if types[i].Kind() != reflect.Ptr {
|
||||||
}
|
return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)}
|
||||||
|
|
||||||
// assume missing params are null values
|
|
||||||
for i := len(params); i < len(callbackArgs); i++ {
|
|
||||||
params = append(params, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
argValues := make([]reflect.Value, len(params))
|
|
||||||
for i, p := range params {
|
|
||||||
// verify that JSON null values are only supplied for optional arguments (ptr types)
|
|
||||||
if p == nil && callbackArgs[i].Kind() != reflect.Ptr {
|
|
||||||
return nil, &invalidParamsError{fmt.Sprintf("invalid or missing value for params[%d]", i)}
|
|
||||||
}
|
|
||||||
if p == nil {
|
|
||||||
argValues[i] = reflect.Zero(callbackArgs[i])
|
|
||||||
} else { // deref pointers values creates previously with reflect.New
|
|
||||||
argValues[i] = reflect.ValueOf(p).Elem()
|
|
||||||
}
|
}
|
||||||
|
args = append(args, reflect.Zero(types[i]))
|
||||||
}
|
}
|
||||||
|
return args, nil
|
||||||
return argValues, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateResponse will create a JSON-RPC success response with the given id and reply as result.
|
// CreateResponse will create a JSON-RPC success response with the given id and reply as result.
|
||||||
|
Loading…
Reference in New Issue
Block a user