divan / gorilla-xmlrpc

Gorilla XML RPC implementation (Golang/Go)
BSD 3-Clause "New" or "Revised" License
69 stars 59 forks source link

XML-RPC server method arguments not parsed correctly (unless I haven't defined the interface correctly) #16

Open daluu opened 7 years ago

daluu commented 7 years ago
/* how to define go gorilla/rpc func signature if XML-RPC args is comprised as
 * 2 arguments: a string argument for actual keyword/method to execute, and
 * an array of any XML-RPC type, to be the actual args for that keyword
 * e.g. sample input
 * <methodCall><methodName>RunKeyword</methodName>
 *   <params>
 *     <param><value><string>KeywordNameToExecute</string></value></param>
 *     <param><value><array><data>
 *       <value><string>keyword_arg1</string></value>
 *       <value><string>keyword_arg2</string></value>
 *     </data></array></value></param>
 *   </params></methodCall>
 */
func (h *RobotRemoteService) RunKeyword(r *http.Request, args ...interface{}, reply *runKeywordReturnType) error {

I'm a novice in go, gorilla/rpc just states that args must be *args. In the above example, args isn't really a struct with members that can be translated to this package's XML-RPC struct. It's not quite an entire array either. The sample signature given report syntax error in my go IDE/editor (Atom).

Or is there no way to do the intended mapping mentioned?

daluu commented 7 years ago

Reviewing the README, package code, and the unit tests, I came up with this, but it still doesn't work right:

type KeywordAndArgsInput struct {
  KeywordName     string
  KeywordAguments []interface{}
}

func (h *RobotRemoteService) RunKeyword(r *http.Request, args *KeywordAndArgsInput, reply *RunKeywordReturnValue) error {
    log.Printf("keyword: %+v\n", args.KeywordName)
    log.Printf("args: %+v\n", args.KeywordAguments)
    for _, a := range args.KeywordAguments {
      log.Printf("arg: %+v\n", a)
      switch reflect.TypeOf(a).Kind() {
      case reflect.Slice:
        log.Printf("args:\n")
        s := reflect.ValueOf(a)
        for i := 0; i < s.Len(); i++ {
          log.Printf("%v: %+v\n", i, s.Index(i))
        }
      default:
        log.Println("Somehow didn't get an array of arguments for keyword.")
      }
    }
    ...
}

serving that over XML-RPC logs the following when I make the XML-RPC request:

2016/10/08 16:29:36 keyword: Test
2016/10/08 16:29:36 args: [<nil> <nil>]
2016/10/08 16:29:36 arg: <nil>
2016/10/08 16:29:36 http: panic serving [::1]:63302: runtime error: invalid memory address or nil pointer dereference
goroutine 5 [running]:
net/http.(*conn).serve.func1(0xc42007ea00)
    /usr/local/go/src/net/http/server.go:1491 +0x12a
panic(0x2c2260, 0xc42000c0b0)
    /usr/local/go/src/runtime/panic.go:458 +0x243
github.com/daluu/gorrs/protocol.(*RobotRemoteService).RunKeyword(0x4a4270, 0xc4200d41e0, 0xc4200115c0, 0xc4200167d0, 0x0, 0x0)
    /Users/daluu/go/src/github.com/daluu/gorrs/protocol/protocol.go:120 +0x267
reflect.Value.call(0xc42007e700, 0xc420032080, 0x13, 0x3106b6, 0x4, 0xc420115bb0, 0x4, 0x4, 0xc4200167d0, 0x304da0, ...)
    /usr/local/go/src/reflect/value.go:434 +0x5c8
reflect.Value.Call(0xc42007e700, 0xc420032080, 0x13, 0xc420115bb0, 0x4, 0x4, 0x0, 0x29d8c, 0xc420043b38)
    /usr/local/go/src/reflect/value.go:302 +0xa4
github.com/gorilla/rpc.(*Server).ServeHTTP(0xc420011110, 0x46b4e0, 0xc420077930, 0xc4200d41e0)
    /Users/daluu/go/src/github.com/gorilla/rpc/server.go:224 +0x4d4
net/http.(*ServeMux).ServeHTTP(0x487a00, 0x46b4e0, 0xc420077930, 0xc4200d41e0)
    /usr/local/go/src/net/http/server.go:2022 +0x7f
net/http.serverHandler.ServeHTTP(0xc42007e980, 0x46b4e0, 0xc420077930, 0xc4200d41e0)
    /usr/local/go/src/net/http/server.go:2202 +0x7d
net/http.(*conn).serve(0xc42007ea00, 0x46b9a0, 0xc420012740)
    /usr/local/go/src/net/http/server.go:1579 +0x4b7
created by net/http.(*Server).Serve
    /usr/local/go/src/net/http/server.go:2293 +0x44d

Looks like the keyword name (string) got unmarshalled correctly, while the array turned to nil, interestingly the array count/length looks correct. How to get the array to unmarshal correctly?

On a related note, if I make a request with an empty array, it runs fine, although I have other issues to work out after getting that far.

What exactly might I be doing wrong in mapping the arguments struct, the XML-RPC service function signature, and the code that parses the arguments in the function?

daluu commented 7 years ago

The failure line in my code from the code snippet posted previously is

switch reflect.TypeOf(a).Kind() {

seems when a non-empty/null array is passed over XML-RPC then we hit this error, else we hit the error in issue #18.