mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
146 lines
3.7 KiB
Go
146 lines
3.7 KiB
Go
package websocket
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/kataras/iris/utils"
|
|
)
|
|
|
|
/*
|
|
serializer, [de]serialize the messages from the client to the server and from the server to the client
|
|
*/
|
|
|
|
// The same values are exists on client side also
|
|
const (
|
|
stringMessageType messageType = iota
|
|
intMessageType
|
|
boolMessageType
|
|
bytesMessageType
|
|
jsonMessageType
|
|
)
|
|
|
|
const (
|
|
prefix = "iris-websocket-message:"
|
|
separator = ";"
|
|
prefixLen = len(prefix)
|
|
separatorLen = len(separator)
|
|
prefixAndSepIdx = prefixLen + separatorLen - 1
|
|
prefixIdx = prefixLen - 1
|
|
separatorIdx = separatorLen - 1
|
|
)
|
|
|
|
var (
|
|
separatorByte = separator[0]
|
|
buf = utils.NewBufferPool(256)
|
|
prefixBytes = []byte(prefix)
|
|
)
|
|
|
|
type (
|
|
messageType uint8
|
|
)
|
|
|
|
func (m messageType) String() string {
|
|
return strconv.Itoa(int(m))
|
|
}
|
|
|
|
func (m messageType) Name() string {
|
|
if m == stringMessageType {
|
|
return "string"
|
|
} else if m == intMessageType {
|
|
return "int"
|
|
} else if m == boolMessageType {
|
|
return "bool"
|
|
} else if m == bytesMessageType {
|
|
return "[]byte"
|
|
} else if m == jsonMessageType {
|
|
return "json"
|
|
}
|
|
|
|
return "Invalid(" + m.String() + ")"
|
|
|
|
}
|
|
|
|
// serialize serializes a custom websocket message from server to be delivered to the client
|
|
// returns the string form of the message
|
|
// Supported data types are: string, int, bool, bytes and JSON.
|
|
func serialize(event string, data interface{}) (string, error) {
|
|
var msgType messageType
|
|
var dataMessage string
|
|
|
|
if s, ok := data.(string); ok {
|
|
msgType = stringMessageType
|
|
dataMessage = s
|
|
} else if i, ok := data.(int); ok {
|
|
msgType = intMessageType
|
|
dataMessage = strconv.Itoa(i)
|
|
} else if b, ok := data.(bool); ok {
|
|
msgType = boolMessageType
|
|
dataMessage = strconv.FormatBool(b)
|
|
} else if by, ok := data.([]byte); ok {
|
|
msgType = bytesMessageType
|
|
dataMessage = string(by)
|
|
} else {
|
|
//we suppose is json
|
|
res, err := json.Marshal(data)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
msgType = jsonMessageType
|
|
dataMessage = string(res)
|
|
}
|
|
|
|
b := buf.Get()
|
|
b.WriteString(prefix)
|
|
b.WriteString(event)
|
|
b.WriteString(separator)
|
|
b.WriteString(msgType.String())
|
|
b.WriteString(separator)
|
|
b.WriteString(dataMessage)
|
|
dataMessage = b.String()
|
|
buf.Put(b)
|
|
|
|
return dataMessage, nil
|
|
|
|
}
|
|
|
|
// deserialize deserializes a custom websocket message from the client
|
|
// ex: iris-websocket-message;chat;4;themarshaledstringfromajsonstruct will return 'hello' as string
|
|
// Supported data types are: string, int, bool, bytes and JSON.
|
|
func deserialize(event string, websocketMessage string) (message interface{}, err error) {
|
|
t, formaterr := strconv.Atoi(websocketMessage[prefixAndSepIdx+len(event)+1 : prefixAndSepIdx+len(event)+2]) // in order to iris-websocket-message;user;-> 4
|
|
if formaterr != nil {
|
|
return nil, formaterr
|
|
}
|
|
_type := messageType(t)
|
|
_message := websocketMessage[prefixAndSepIdx+len(event)+3:] // in order to iris-websocket-message;user;4; -> themarshaledstringfromajsonstruct
|
|
|
|
if _type == stringMessageType {
|
|
message = string(_message)
|
|
} else if _type == intMessageType {
|
|
message, err = strconv.Atoi(_message)
|
|
} else if _type == boolMessageType {
|
|
message, err = strconv.ParseBool(_message)
|
|
} else if _type == bytesMessageType {
|
|
message = []byte(_message)
|
|
} else if _type == jsonMessageType {
|
|
err = json.Unmarshal([]byte(_message), message)
|
|
} else {
|
|
return nil, fmt.Errorf("Type %s is invalid for message: %s", _type.Name(), websocketMessage)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// getCustomEvent return empty string when the websocketMessage is native message
|
|
func getCustomEvent(websocketMessage string) string {
|
|
if len(websocketMessage) < prefixAndSepIdx {
|
|
return ""
|
|
}
|
|
s := websocketMessage[prefixAndSepIdx:]
|
|
evt := s[:strings.IndexByte(s, separatorByte)]
|
|
return evt
|
|
}
|