Thank you for the amazing websocket plugin. Its very simple to use.
Since I would like to avoid global variables, I want to pass a custom struct to the websocket handler. I tried overloading the handler function, but I get "used as value" error.
Here is the calling function and handler
func handleWSconnection(c websocket.Connection, s myStruct) {
//...
}
func main(){
// ...
var c websocket.Connection
ws.OnConnection(handleWSconnection(c, myStruct))
// ...
}
This is the error in the command line
# command-line-arguments
./app.go:23:36: handleWSconnection(c, myStruct) used as value
Please suggest how to handle this scenario. Thanks in advance.
func handleWSconnection(s myStruct) func(websocket.Connection) {
return func(c websocket.Connection) {
// ...use of "s" + websocket conn here
}
)
ws.OnConnection(handleWSconnection(myStructInstance))
Thank you so much.
You are very welcomed!
@kataras, Unfortunately there seems to be an issue with this setup. The Websocket handler gets triggered multiple times when additional users trigger the websocket handler. When there is only one user, the websocket gets triggered once. When a second user triggers the same websocket, it gets triggered twice for the second user, 3 times for the 3rd user and so on.
How do I make the handler trigger only once ?
Here is sample code, could you please suggest where things are going wrong here...
func handleWSconnection(s *mySession) func(websocket.Connection) {
return func(c websocket.Connection) {
c.On("tick", func(str string) {
// This gets triggered MULTIPLE TIMES
}
}
)
func main(){
//........
//........
ws := websocket.New(websocket.Config{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
EnableCompression: true,
})
app.Get("/", func(ctx iris.Context) {
goSession := sess.Start(ctx)
userId, err := goSession.GetInt("userId")
currentSession := &userSession {
uid: userId,
}
ws.OnConnection(handleWSconnection(currentSession))
}
app.Any("/ws", ws.Handler())
app.Any("/iris-ws.js", func(ctx iris.Context) {
ctx.Write(websocket.ClientSource)
})
}
@kickbox ws.OnConnection is server's event and it should be called before your ws.Handler() as examples explaining, so Handler() uses them. You can't add listeners for each time a handler is executed, the "multi triggers" you explained is the logical behavior for your code, I will explain you now but please read the examples more carefully.
You have two ways to deal context access inside websocket handler or a websocket connection inside a context (the same thing but opossite logical-flow), read below:
If you need access to the ctx iris.Context the websocket.Conn has a Context() function which will give you the Context access you need to initialize the session you need. If you open a code editor and type c. inside your weboskcet connection handler you can see the Context() method.
func handleWSconnection(c websocket.Connection) {
ctx := c.Context()
goSession := sess.Start(ctx)
userId, err := goSession.GetInt("userId")
currentSession := &userSession{
uid: userId,
}
//
// register your functions to that conn.
//
c.On("tick", func(str string) {
// use the `currentSession` here.
})
}
func main(){
//........
//........
ws := websocket.New(websocket.Config{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
EnableCompression: true,
})
// register the listener once, so each connection goes through that
// handleWSconnection
ws.OnConnection(handleWSconnection)
app.Any("/ws", ws.Handler()) // use /ws or /, you know.
app.Any("/iris-ws.js", func(ctx iris.Context) { // or ("/ iris-ws.js", ws.ClientHandler())
ctx.Write(websocket.ClientSource)
})
}
Secondly, If you want to upgrade the http to websocket inside an HTTP handler you can do it by using the ws.Upgrade(ctx) function and remove the ws.Connection and app.Any("/ws", ws.Handler()) because you will handle these by your own now, example:
package main
func handleWSconnectionWithSession(c websocket.Connection, s *mySession) {
c.On("tick", func(str string) {
// [...]
})
}
func main() {
//........
//........
ws := websocket.New(websocket.Config{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
EnableCompression: true,
})
app.Any("/ws", func(ctx iris.Context) {
goSession := sess.Start(ctx)
userId, err := goSession.GetInt("userId")
currentSession := &userSession{
uid: userId,
}
c := ws.Upgrade(ctx)
if c.Err() != nil {
return
}
//
// start the websocket work here
//
handleWSconnectionWithSession(c, currentSession)
//
// end your custom websocket work here.
//
// call `Wait` in order to block the handler
// and to 'activate' the connection's events.
c.Wait()
})
app.Any("/iris-ws.js", func(ctx iris.Context) { // or ("/ iris-ws.js", ws.ClientHandler())
ctx.Write(websocket.ClientSource)
})
}
Thank you so much @kataras. I really appreciate your examples and thank you for taking the time to write two more example here on WebSocket. The ease of use and the abundance of examples in iris is what led me to use your package. Thanks again. I will surely look at examples in more detail.
Most helpful comment
@kataras, Unfortunately there seems to be an issue with this setup. The Websocket handler gets triggered multiple times when additional users trigger the websocket handler. When there is only one user, the websocket gets triggered once. When a second user triggers the same websocket, it gets triggered twice for the second user, 3 times for the 3rd user and so on.
How do I make the handler trigger only once ?
Here is sample code, could you please suggest where things are going wrong here...