diff --git a/HISTORY.md b/HISTORY.md index 9474eb4b..5dd34ab4 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -17,6 +17,32 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene **How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris` or let the automatic updater do that for you. +# Su, 28 October 2018 | v11.0.1 + +- Update benchmarks: https://github.com/kataras/iris/commit/d1b47b1ec65ae77a2ca7485e510386f4a5456ac4 +- Add link for third-party source benchmarks: https://github.com/kataras/iris/commit/64e80a7ee5c23ed938ddc8b68d181a25420c7653 +- Add optionally custom low-level websocket message data prefix as requested at: https://github.com/kataras/iris/issues/1113 by [@jjhesk](https://github.com/jjhesk). Example: + +```go +app := iris.New() + +// [...] +wsServer := websocket.New(websocket.Config{ + // [...] + EvtMessagePrefix: []byte("my-custom-prefix:"), +}) + +// [...] + +// serve the javascript built'n client-side library, +// see websockets.html script tags, this path is used. +app.Any("/iris-ws.js", func(ctx iris.Context) { + ctx.Write(wsServer.ClientSource) +}) + +// [...] +``` + # Su, 21 October 2018 | v11.0.0 For the craziest of us, click [here](https://github.com/kataras/iris/compare/v10.7.0...v11) 🔥 to find out the commits and the code changes since our previous release. diff --git a/HISTORY_GR.md b/HISTORY_GR.md index 98a1c416..6993506e 100644 --- a/HISTORY_GR.md +++ b/HISTORY_GR.md @@ -17,9 +17,13 @@ **Πώς να αναβαθμίσετε**: Ανοίξτε την γραμμή εντολών σας και εκτελέστε αυτήν την εντολή: `go get -u github.com/kataras/iris` ή αφήστε το αυτόματο updater να το κάνει αυτό για σας. +# Su, 28 October 2018 | v11.0.1 + +Πατήστε [εδώ](https://github.com/kataras/iris/blob/master/HISTORY.md#su-28-october-2018--v1101) για να διαβάσετε στα αγγλικά τις αλλαγές και το νέο feature που φέρνει το τελευταίο patch για την έκδοση 11. + # Su, 21 October 2018 | v11.0.0 -Πατήστε [εδώ](https://github.com/kataras/iris/blob/master/HISTORY.md#su-21-october-2018--v11) για να διαβάσετε στα αγγλικά τις αλλαγές και τα νέα features που φέρνει νεότερη έκδοση του Iris, version 11. +Πατήστε [εδώ](https://github.com/kataras/iris/blob/master/HISTORY.md#su-21-october-2018--v1100) για να διαβάσετε στα αγγλικά τις αλλαγές και τα νέα features που φέρνει νεότερη έκδοση του Iris, version 11. # Sat, 11 August 2018 | v10.7.0 diff --git a/HISTORY_ID.md b/HISTORY_ID.md index 36e30885..f49ea7fd 100644 --- a/HISTORY_ID.md +++ b/HISTORY_ID.md @@ -17,9 +17,13 @@ Developers tidak diwajibkan untuk melakukan upgrade apabila mereka tidak membutu **Cara Upgrade**: Bukan command-line anda dan eksekuis perintah ini: `go get -u github.com/kataras/iris` atau biarkan updater otomatis melakukannya untuk anda. +# Su, 28 October 2018 | v11.0.1 + +This history entry is not translated yet to the Indonesian language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#su-28-october-2018--v1101) instead. + # Su, 21 October 2018 | v11.0.0 -This history entry is not translated yet to the Indonesian language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#su-21-october-2018--v11) instead. +This history entry is not translated yet to the Indonesian language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#su-21-october-2018--v1100) instead. # Sat, 11 August 2018 | v10.7.0 diff --git a/HISTORY_ZH.md b/HISTORY_ZH.md index 7ee04145..ce319e94 100644 --- a/HISTORY_ZH.md +++ b/HISTORY_ZH.md @@ -17,9 +17,13 @@ **如何升级**: 打开命令行执行以下命令: `go get -u github.com/kataras/iris` 或者等待自动更新。 +# Su, 28 October 2018 | v11.0.1 + +This history entry is not translated yet to the Chinese language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#su-28-october-2018--v1101) instead. + # Su, 21 October 2018 | v11.0.0 -This history entry is not translated yet to the Chinese language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#su-21-october-2018--v11) instead. +This history entry is not translated yet to the Chinese language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#su-21-october-2018--v1100) instead. # Sat, 11 August 2018 | v10.7.0 diff --git a/README.md b/README.md index efb9cc2a..29d72631 100644 --- a/README.md +++ b/README.md @@ -1011,7 +1011,7 @@ Iris, unlike others, is 100% compatible with the standards and that's why the ma ## Support -- [HISTORY](HISTORY.md#su-21-october-2018--v1100) file is your best friend, it contains information about the latest features and changes +- [HISTORY](HISTORY.md#su-28-october-2018--v1101) file is your best friend, it contains information about the latest features and changes - Did you happen to find a bug? Post it at [github issues](https://github.com/kataras/iris/issues) - Do you have any questions or need to speak with someone experienced to solve a problem at real-time? Join us to the [community chat](https://chat.iris-go.com) - Complete our form-based user experience report by clicking [here](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link) diff --git a/VERSION b/VERSION index 236610e0..ff11019b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -11.0.0:https://github.com/kataras/iris/blob/master/HISTORY.md#su-21-october-2018--v1100 \ No newline at end of file +11.0.1:https://github.com/kataras/iris/blob/master/HISTORY.md#su-28-october-2018--v1101 \ No newline at end of file diff --git a/_examples/websocket/chat/main.go b/_examples/websocket/chat/main.go index fce0a664..e3f18b15 100644 --- a/_examples/websocket/chat/main.go +++ b/_examples/websocket/chat/main.go @@ -26,8 +26,13 @@ func main() { func setupWebsocket(app *iris.Application) { // create our echo websocket server ws := websocket.New(websocket.Config{ + // These are low-level optionally fields, + // user/client can't see those values. ReadBufferSize: 1024, WriteBufferSize: 1024, + // only javascript client-side code has the same rule, + // which you serve using the ws.ClientSource (see below). + EvtMessagePrefix: []byte("my-custom-prefix:"), }) ws.OnConnection(handleConnection) @@ -38,7 +43,7 @@ func setupWebsocket(app *iris.Application) { // serve the javascript built'n client-side library, // see websockets.html script tags, this path is used. app.Any("/iris-ws.js", func(ctx iris.Context) { - ctx.Write(websocket.ClientSource) + ctx.Write(ws.ClientSource) }) } diff --git a/_examples/websocket/custom-go-client/main.go b/_examples/websocket/custom-go-client/main.go index da199b5a..32ff53db 100644 --- a/_examples/websocket/custom-go-client/main.go +++ b/_examples/websocket/custom-go-client/main.go @@ -89,7 +89,7 @@ func SendMessage(serverID, to, method, message string) error { func SendtBytes(serverID, to, method string, message []byte) error { // look https://github.com/kataras/iris/blob/master/websocket/message.go , client.go and client.js // to understand the buffer line: - buffer := []byte(fmt.Sprintf("iris-websocket-message:%v;0;%v;%v;", method, serverID, to)) + buffer := []byte(fmt.Sprintf("%s%v;0;%v;%v;", websocket.DefaultEvtMessageKey, method, serverID, to)) buffer = append(buffer, message...) _, err := WS.Write(buffer) if err != nil { diff --git a/doc.go b/doc.go index 6c8bb567..00ab6377 100644 --- a/doc.go +++ b/doc.go @@ -35,7 +35,7 @@ Source code and other details for the project are available at GitHub: Current Version -11.0.0 +11.0.1 Installation diff --git a/iris.go b/iris.go index 5660847b..c0ba637d 100644 --- a/iris.go +++ b/iris.go @@ -33,7 +33,7 @@ import ( var ( // Version is the current version number of the Iris Web Framework. - Version = "11.0.0" + Version = "11.0.1" ) // HTTP status codes as registered with IANA. diff --git a/websocket/client.go b/websocket/client.go index 771e5eb8..2144411a 100644 --- a/websocket/client.go +++ b/websocket/client.go @@ -7,7 +7,7 @@ import ( ) // ClientHandler is the handler which serves the javascript client-side -// library. It uses a small cache based on the iris/context.StaticCacheDuration. +// library. It uses a small cache based on the iris/context.WriteWithExpiration. func ClientHandler() context.Handler { modNow := time.Now() return func(ctx context.Context) { @@ -20,12 +20,12 @@ func ClientHandler() context.Handler { } } -// ClientSource the client-side javascript raw source code +// ClientSource the client-side javascript raw source code. var ClientSource = []byte(`var websocketStringMessageType = 0; var websocketIntMessageType = 1; var websocketBoolMessageType = 2; var websocketJSONMessageType = 4; -var websocketMessagePrefix = "iris-websocket-message:"; +var websocketMessagePrefix = "` + DefaultEvtMessageKey + `"; var websocketMessageSeparator = ";"; var websocketMessagePrefixLen = websocketMessagePrefix.length; var websocketMessageSeparatorLen = websocketMessageSeparator.length; diff --git a/websocket/config.go b/websocket/config.go index cc0ac310..68be4f75 100644 --- a/websocket/config.go +++ b/websocket/config.go @@ -1,10 +1,13 @@ package websocket import ( + "math/rand" "net/http" "time" "github.com/kataras/iris/context" + + "github.com/iris-contrib/go.uuid" ) const ( @@ -22,15 +25,24 @@ const ( DefaultWebsocketReadBufferSize = 4096 // DefaultWebsocketWriterBufferSize 4096 DefaultWebsocketWriterBufferSize = 4096 - // DefaultClientSourcePath "/iris-ws.js" - DefaultClientSourcePath = "/iris-ws.js" + // DefaultEvtMessageKey is the default prefix of the underline websocket events + // that are being established under the hoods. + // + // Defaults to "iris-websocket-message:". + // Last character of the prefix should be ':'. + DefaultEvtMessageKey = "iris-websocket-message:" ) var ( - // DefaultIDGenerator returns the result of 64 - // random combined characters as the id of a new connection. - // Used when config.IDGenerator is nil - DefaultIDGenerator = func(context.Context) string { return randomString(64) } + // DefaultIDGenerator returns a random unique for a new connection. + // Used when config.IDGenerator is nil. + DefaultIDGenerator = func(context.Context) string { + id, err := uuid.NewV4() + if err != nil { + return randomString(64) + } + return id.String() + } ) // Config the websocket server configuration @@ -38,9 +50,16 @@ var ( type Config struct { // IDGenerator used to create (and later on, set) // an ID for each incoming websocket connections (clients). - // The request is an argument which you can use to generate the ID (from headers for example). + // The request is an input parameter which you can use to generate the ID (from headers for example). // If empty then the ID is generated by DefaultIDGenerator: randomString(64) IDGenerator func(ctx context.Context) string + // EvtMessagePrefix is the prefix of the underline websocket events that are being established under the hoods. + // This prefix is visible only to the javascript side (code) and it has nothing to do + // with the message that the end-user receives. + // Do not change it unless it is absolutely necessary. + // + // If empty then defaults to []byte("iris-websocket-message:"). + EvtMessagePrefix []byte // Error is the function that will be fired if any client couldn't upgrade the HTTP connection // to a websocket connection, a handshake error. Error func(w http.ResponseWriter, r *http.Request, status int, reason error) @@ -135,9 +154,47 @@ func (c Config) Validate() Config { } } + if len(c.EvtMessagePrefix) == 0 { + c.EvtMessagePrefix = []byte(DefaultEvtMessageKey) + } + if c.IDGenerator == nil { c.IDGenerator = DefaultIDGenerator } return c } + +const ( + letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + letterIdxBits = 6 // 6 bits to represent a letter index + letterIdxMask = 1<= 0; { + if remain == 0 { + cache, remain = src.Int63(), letterIdxMax + } + if idx := int(cache & letterIdxMask); idx < len(letterBytes) { + b[i] = letterBytes[idx] + i-- + } + cache >>= letterIdxBits + remain-- + } + + return b +} + +// randomString accepts a number(10 for example) and returns a random string using simple but fairly safe random algorithm +func randomString(n int) string { + return string(random(n)) +} diff --git a/websocket/connection.go b/websocket/connection.go index 4d1ec8ab..1d373af0 100644 --- a/websocket/connection.go +++ b/websocket/connection.go @@ -415,15 +415,15 @@ func (c *connection) startReader() { // messageReceived checks the incoming message and fire the nativeMessage listeners or the event listeners (ws custom message) func (c *connection) messageReceived(data []byte) { - if bytes.HasPrefix(data, websocketMessagePrefixBytes) { - customData := string(data) + if bytes.HasPrefix(data, c.server.config.EvtMessagePrefix) { //it's a custom ws message - receivedEvt := getWebsocketCustomEvent(customData) - listeners := c.onEventListeners[receivedEvt] - if listeners == nil { // if not listeners for this event exit from here - return + receivedEvt := c.server.messageSerializer.getWebsocketCustomEvent(data) + listeners, ok := c.onEventListeners[string(receivedEvt)] + if !ok || len(listeners) == 0 { + return // if not listeners for this event exit from here } - customMessage, err := websocketMessageDeserialize(receivedEvt, customData) + + customMessage, err := c.server.messageSerializer.deserialize(receivedEvt, data) if customMessage == nil || err != nil { return } diff --git a/websocket/emitter.go b/websocket/emitter.go index 859bf0ee..d8ae087d 100644 --- a/websocket/emitter.go +++ b/websocket/emitter.go @@ -34,10 +34,10 @@ func (e *emitter) EmitMessage(nativeMessage []byte) error { } func (e *emitter) Emit(event string, data interface{}) error { - message, err := websocketMessageSerialize(event, data) + message, err := e.conn.server.messageSerializer.serialize(event, data) if err != nil { return err } - e.EmitMessage([]byte(message)) + e.EmitMessage(message) return nil } diff --git a/websocket/message.go b/websocket/message.go index f5e4f29e..804baa3c 100644 --- a/websocket/message.go +++ b/websocket/message.go @@ -1,179 +1,181 @@ package websocket import ( + "bytes" + "encoding/binary" "encoding/json" - "math/rand" "strconv" - "strings" - "time" "github.com/kataras/iris/core/errors" "github.com/valyala/bytebufferpool" ) -// The same values are exists on client side also -const ( - websocketStringMessageType websocketMessageType = iota - websocketIntMessageType - websocketBoolMessageType - websocketBytesMessageType - websocketJSONMessageType -) - -const ( - websocketMessagePrefix = "iris-websocket-message:" - websocketMessageSeparator = ";" - websocketMessagePrefixLen = len(websocketMessagePrefix) - websocketMessageSeparatorLen = len(websocketMessageSeparator) - websocketMessagePrefixAndSepIdx = websocketMessagePrefixLen + websocketMessageSeparatorLen - 1 - websocketMessagePrefixIdx = websocketMessagePrefixLen - 1 - websocketMessageSeparatorIdx = websocketMessageSeparatorLen - 1 -) - -var ( - websocketMessageSeparatorByte = websocketMessageSeparator[0] - websocketMessageBuffer = bytebufferpool.Pool{} - websocketMessagePrefixBytes = []byte(websocketMessagePrefix) -) - type ( - websocketMessageType uint8 + messageType uint8 ) -func (m websocketMessageType) String() string { +func (m messageType) String() string { return strconv.Itoa(int(m)) } -func (m websocketMessageType) Name() string { - if m == websocketStringMessageType { +func (m messageType) Name() string { + switch m { + case messageTypeString: return "string" - } else if m == websocketIntMessageType { + case messageTypeInt: return "int" - } else if m == websocketBoolMessageType { + case messageTypeBool: return "bool" - } else if m == websocketBytesMessageType { + case messageTypeBytes: return "[]byte" - } else if m == websocketJSONMessageType { + case messageTypeJSON: return "json" + default: + return "Invalid(" + m.String() + ")" } - - return "Invalid(" + m.String() + ")" - } +// The same values are exists on client side too. +const ( + messageTypeString messageType = iota + messageTypeInt + messageTypeBool + messageTypeBytes + messageTypeJSON +) + +const ( + messageSeparator = ";" +) + +var messageSeparatorByte = messageSeparator[0] + +type messageSerializer struct { + prefix []byte + + prefixLen int + separatorLen int + prefixAndSepIdx int + prefixIdx int + separatorIdx int + + buf *bytebufferpool.Pool +} + +func newMessageSerializer(messagePrefix []byte) *messageSerializer { + return &messageSerializer{ + prefix: messagePrefix, + prefixLen: len(messagePrefix), + separatorLen: len(messageSeparator), + prefixAndSepIdx: len(messagePrefix) + len(messageSeparator) - 1, + prefixIdx: len(messagePrefix) - 1, + separatorIdx: len(messageSeparator) - 1, + + buf: new(bytebufferpool.Pool), + } +} + +var ( + boolTrueB = []byte("true") + boolFalseB = []byte("false") +) + // websocketMessageSerialize serializes a custom websocket message from websocketServer to be delivered to the client // returns the string form of the message // Supported data types are: string, int, bool, bytes and JSON. -func websocketMessageSerialize(event string, data interface{}) (string, error) { - var msgType websocketMessageType - var dataMessage string +func (ms *messageSerializer) serialize(event string, data interface{}) ([]byte, error) { + b := ms.buf.Get() + b.Write(ms.prefix) + b.WriteString(event) + b.WriteByte(messageSeparatorByte) - if s, ok := data.(string); ok { - msgType = websocketStringMessageType - dataMessage = s - } else if i, ok := data.(int); ok { - msgType = websocketIntMessageType - dataMessage = strconv.Itoa(i) - } else if b, ok := data.(bool); ok { - msgType = websocketBoolMessageType - dataMessage = strconv.FormatBool(b) - } else if by, ok := data.([]byte); ok { - msgType = websocketBytesMessageType - dataMessage = string(by) - } else { + switch v := data.(type) { + case string: + b.WriteString(messageTypeString.String()) + b.WriteByte(messageSeparatorByte) + b.WriteString(v) + case int: + b.WriteString(messageTypeInt.String()) + b.WriteByte(messageSeparatorByte) + binary.Write(b, binary.LittleEndian, v) + case bool: + b.WriteString(messageTypeBool.String()) + b.WriteByte(messageSeparatorByte) + if v { + b.Write(boolTrueB) + } else { + b.Write(boolFalseB) + } + case []byte: + b.WriteString(messageTypeBytes.String()) + b.WriteByte(messageSeparatorByte) + b.Write(v) + default: //we suppose is json res, err := json.Marshal(data) if err != nil { - return "", err + return nil, err } - msgType = websocketJSONMessageType - dataMessage = string(res) + b.WriteString(messageTypeJSON.String()) + b.WriteByte(messageSeparatorByte) + b.Write(res) } - b := websocketMessageBuffer.Get() - b.WriteString(websocketMessagePrefix) - b.WriteString(event) - b.WriteString(websocketMessageSeparator) - b.WriteString(msgType.String()) - b.WriteString(websocketMessageSeparator) - b.WriteString(dataMessage) - dataMessage = b.String() - websocketMessageBuffer.Put(b) - - return dataMessage, nil + message := b.Bytes() + ms.buf.Put(b) + return message, nil } var errInvalidTypeMessage = errors.New("Type %s is invalid for message: %s") -// websocketMessageDeserialize deserializes a custom websocket message from the client +// 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 websocketMessageDeserialize(event string, websocketMessage string) (message interface{}, err error) { - t, formaterr := strconv.Atoi(websocketMessage[websocketMessagePrefixAndSepIdx+len(event)+1 : websocketMessagePrefixAndSepIdx+len(event)+2]) // in order to iris-websocket-message;user;-> 4 - if formaterr != nil { - return nil, formaterr - } - _type := websocketMessageType(t) - _message := websocketMessage[websocketMessagePrefixAndSepIdx+len(event)+3:] // in order to iris-websocket-message;user;4; -> themarshaledstringfromajsonstruct - - if _type == websocketStringMessageType { - message = string(_message) - } else if _type == websocketIntMessageType { - message, err = strconv.Atoi(_message) - } else if _type == websocketBoolMessageType { - message, err = strconv.ParseBool(_message) - } else if _type == websocketBytesMessageType { - message = []byte(_message) - } else if _type == websocketJSONMessageType { - err = json.Unmarshal([]byte(_message), &message) - } else { - return nil, errInvalidTypeMessage.Format(_type.Name(), websocketMessage) +func (ms *messageSerializer) deserialize(event []byte, websocketMessage []byte) (interface{}, error) { + dataStartIdx := ms.prefixAndSepIdx + len(event) + 3 + if len(websocketMessage) <= dataStartIdx { + return nil, errors.New("websocket invalid message: " + string(websocketMessage)) } - return + typ, err := strconv.Atoi(string(websocketMessage[ms.prefixAndSepIdx+len(event)+1 : ms.prefixAndSepIdx+len(event)+2])) // in order to iris-websocket-message;user;-> 4 + if err != nil { + return nil, err + } + + data := websocketMessage[dataStartIdx:] // in order to iris-websocket-message;user;4; -> themarshaledstringfromajsonstruct + + switch messageType(typ) { + case messageTypeString: + return string(data), nil + case messageTypeInt: + msg, err := strconv.Atoi(string(data)) + if err != nil { + return nil, err + } + return msg, nil + case messageTypeBool: + if bytes.Equal(data, boolTrueB) { + return true, nil + } + return false, nil + case messageTypeBytes: + return data, nil + case messageTypeJSON: + var msg interface{} + err := json.Unmarshal(data, &msg) + return msg, err + default: + return nil, errInvalidTypeMessage.Format(messageType(typ).Name(), websocketMessage) + } } // getWebsocketCustomEvent return empty string when the websocketMessage is native message -func getWebsocketCustomEvent(websocketMessage string) string { - if len(websocketMessage) < websocketMessagePrefixAndSepIdx { - return "" +func (ms *messageSerializer) getWebsocketCustomEvent(websocketMessage []byte) []byte { + if len(websocketMessage) < ms.prefixAndSepIdx { + return nil } - s := websocketMessage[websocketMessagePrefixAndSepIdx:] - evt := s[:strings.IndexByte(s, websocketMessageSeparatorByte)] + s := websocketMessage[ms.prefixAndSepIdx:] + evt := s[:bytes.IndexByte(s, messageSeparatorByte)] return evt } - -const ( - letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - letterIdxBits = 6 // 6 bits to represent a letter index - letterIdxMask = 1<= 0; { - if remain == 0 { - cache, remain = src.Int63(), letterIdxMax - } - if idx := int(cache & letterIdxMask); idx < len(letterBytes) { - b[i] = letterBytes[idx] - i-- - } - cache >>= letterIdxBits - remain-- - } - - return b -} - -// randomString accepts a number(10 for example) and returns a random string using simple but fairly safe random algorithm -func randomString(n int) string { - return string(random(n)) -} diff --git a/websocket/server.go b/websocket/server.go index a88f1806..28a25992 100644 --- a/websocket/server.go +++ b/websocket/server.go @@ -1,6 +1,7 @@ package websocket import ( + "bytes" "sync" "github.com/kataras/iris/context" @@ -34,7 +35,15 @@ type ( // // To serve the built'n javascript client-side library look the `websocket.ClientHandler`. Server struct { - config Config + config Config + // ClientSource contains the javascript side code + // for the iris websocket communication + // based on the configuration's `EvtMessagePrefix`. + // + // Use a route to serve this file on a specific path, i.e + // app.Any("/iris-ws.js", func(ctx iris.Context) { ctx.Write(mywebsocketServer.ClientSource) }) + ClientSource []byte + messageSerializer *messageSerializer connections sync.Map // key = the Connection ID. rooms map[string][]string // by default a connection is joined to a room which has the connection id as its name mu sync.RWMutex // for rooms. @@ -53,6 +62,8 @@ func New(cfg Config) *Server { cfg = cfg.Validate() return &Server{ config: cfg, + ClientSource: bytes.Replace(ClientSource, []byte(DefaultEvtMessageKey), cfg.EvtMessagePrefix, -1), + messageSerializer: newMessageSerializer(cfg.EvtMessagePrefix), connections: sync.Map{}, // ready-to-use, this is not necessary. rooms: make(map[string][]string), onConnectionListeners: make([]ConnectionFunc, 0),