Open oldshuren opened 7 years ago
For the time being, you can just use json.RawMessage as the parameter and get a byte slice. I'm sure type checking would perform better though.
That's not working for me :D
It turns out our upstream service is... unique and is sending back 3 parameters...
{"some":"json":"blob":true},"{\"status\":200,\"data\":{},\"message\":\"Ok\"}",6895206,
original request, response, some integer
json.RawMessage doesn't let me parse it, interface, string, []byte...
Always end up with invalid character ',' after top-level value
edit: Raw frame:
42["deferred",{"some":"json":"blob":true},"{\"status\":200,\"data\":{},\"message\":\"Ok\"}",6895206]
edit: I solved mine with the following patch which permits on funcs with multiple arguments
diff --git a/caller.go b/caller.go
index bb423dd..5d25108 100644
--- a/caller.go
+++ b/caller.go
@@ -7,7 +7,7 @@ import (
type caller struct {
Func reflect.Value
- Args reflect.Type
+ Args []reflect.Type
ArgsPresent bool
Out bool
}
@@ -40,8 +40,11 @@ func newCaller(f interface{}) (*caller, error) {
if fType.NumIn() == 1 {
curCaller.Args = nil
curCaller.ArgsPresent = false
- } else if fType.NumIn() == 2 {
- curCaller.Args = fType.In(1)
+ } else if fType.NumIn() >= 2 {
+ curCaller.Args = make([]reflect.Type, fType.NumIn()-1)
+ for i := range curCaller.Args {
+ curCaller.Args[i] = fType.In(i + 1)
+ }
curCaller.ArgsPresent = true
} else {
return nil, ErrorCallerNot2Args
@@ -53,23 +56,27 @@ func newCaller(f interface{}) (*caller, error) {
/**
returns function parameter as it is present in it using reflection
*/
-func (c *caller) getArgs() interface{} {
- return reflect.New(c.Args).Interface()
+func (c *caller) getArgs() []interface{} {
+ res := make([]interface{}, len(c.Args))
+ for i, v := range c.Args {
+ res[i] = reflect.New(v).Interface()
+ }
+ return res
}
/**
calls function with given arguments from its representation using reflection
*/
-func (c *caller) callFunc(h *Channel, args interface{}) []reflect.Value {
+func (c *caller) callFunc(h *Channel, args []interface{}) []reflect.Value {
//nil is untyped, so use the default empty value of correct type
if args == nil {
args = c.getArgs()
}
-
- a := []reflect.Value{reflect.ValueOf(h), reflect.ValueOf(args).Elem()}
- if !c.ArgsPresent {
- a = a[0:1]
+ vals := make([]reflect.Value, len(args)+1)
+ vals[0] = reflect.ValueOf(h)
+ for i, v := range args {
+ vals[i+1] = reflect.ValueOf(v).Elem()
}
- return c.Func.Call(a)
+ return c.Func.Call(vals)
}
diff --git a/handler.go b/handler.go
index 78c3636..59cce04 100644
--- a/handler.go
+++ b/handler.go
@@ -2,9 +2,11 @@ package gosocketio
import (
"encoding/json"
- "github.com/graarh/golang-socketio/protocol"
- "sync"
+ "fmt"
"reflect"
+ "sync"
+
+ "github.com/graarh/golang-socketio/protocol"
)
const (
@@ -48,7 +50,6 @@ func (m *methods) On(method string, f interface{}) error {
m.messageHandlersLock.Lock()
defer m.messageHandlersLock.Unlock()
m.messageHandlers[method] = c
-
return nil
}
@@ -58,7 +59,6 @@ Find message processing function associated with given method
func (m *methods) findMethod(method string) (*caller, bool) {
m.messageHandlersLock.RLock()
defer m.messageHandlersLock.RUnlock()
-
f, ok := m.messageHandlers[method]
return f, ok
}
@@ -76,7 +76,7 @@ func (m *methods) callLoopEvent(c *Channel, event string) {
return
}
- f.callFunc(c, &struct{}{})
+ f.callFunc(c, nil)
}
/**
@@ -94,13 +94,14 @@ func (m *methods) processIncomingMessage(c *Channel, msg *protocol.Message) {
}
if !f.ArgsPresent {
- f.callFunc(c, &struct{}{})
+ f.callFunc(c, nil)
return
}
data := f.getArgs()
- err := json.Unmarshal([]byte(msg.Args), &data)
+ err := json.Unmarshal([]byte("["+msg.Args+"]"), &data)
if err != nil {
+ fmt.Printf("Error processing message. msg.Args: %v, data: %v, err: %v\n", msg.Args, data, err)
return
}
@@ -120,10 +121,9 @@ func (m *methods) processIncomingMessage(c *Channel, msg *protocol.Message) {
if err != nil {
return
}
-
result = f.callFunc(c, data)
} else {
- result = f.callFunc(c, &struct{}{})
+ result = f.callFunc(c, nil)
}
ack := &protocol.Message{
diff --git a/send.go b/send.go
index 07e8130..386a196 100644
--- a/send.go
+++ b/send.go
@@ -3,9 +3,10 @@ package gosocketio
import (
"encoding/json"
"errors"
- "github.com/graarh/golang-socketio/protocol"
"log"
"time"
+
+ "github.com/graarh/golang-socketio/protocol"
)
var (
@@ -32,7 +33,6 @@ func send(msg *protocol.Message, c *Channel, args interface{}) error {
msg.Args = string(json)
}
-
command, err := protocol.Encode(msg)
if err != nil {
return err
how you solved this issue?
I think handler.go should detect that if the user callback argument is string type. Just call the callback directly without json.Unmarshall. Same for send.go, if the args type is string, don't call json.Marshall.
Because sometimes we want just to a partial json decoding. Or we can use easyjson's generated code to do Marshall/Unmarshall
Thanks!