Gorilla chat example not working (server immediately closes connection)

325 views
Skip to first unread message

Richard Grosman

unread,
Apr 4, 2019, 3:58:23 AM4/4/19
to Gorilla web toolkit
Hi,

I want to build a simple chat app. As a web framework in general I use echo.Labstack and for this app I want to use gorilla.websocket to support multiple clients (broadcasting hub). I'm new to all of this so please apologize beginner mistakes.

This is the example for the chat app:


Here you can find the WebSocket Recipe provided by echo (Labstack) https://echo.labstack.com/cookbook/websocket

My handlerfunc looks like this:
func webchatHandler(c echo.Context) error {

    req := c.Request()
   res := c.Response()

    ws, err := upgrader.Upgrade(res, req, nil)
   if err != nil {
       return err
   }
   log.Println("ws upgrader.Upgrade")
   defer ws.Close()
   log.Println("defer ws.Close()")

    hub := createHub()
   log.Printf("hub created Hub: %T %v\n", hub, hub)
   go hub.run()
   log.Println("hub running")
   go handleWSRequests(hub, ws)

    return err
}

handleWSRequests(hub,ws):
func handleWSRequests(hub *Hub, ws *websocket.Conn) error {

    client := &Client{hub: hub, conn: ws, send: make(chan []byte, 512)}
   client.hub.register <- client
   _, error := fmt.Println("new client object and client.hub.register<-client")

    go client.readPump()
   go client.writePump()

    return error
}

The problem is now that the server immediately closes the connection.

To figure out what is going behind, I added some Println statements. This is the log output:

   ____    __
 / __/___/ /  ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.0.0
High performance, minimalist Go web framework
____________________________________O/_______
                                   O\
⇨ http server started on [::]:80
2019/04/03 20:46:22 ws upgrader.Upgrade
2019/04/03 20:46:22 defer ws.Close()
2019/04/03 20:46:22 hub created Hub: *main.Hub &{map[] 0xc000188c00 0xc000188c60 0xc000188cc0}
2019/04/03 20:46:22 hub running
new client object and client.hub.register<-client
h.register Client registered
2019/04/03 20:46:22 message c.conn.ReadMessage(): []
{"time":"2019-04-03T20:46:22.6634142+02:00","id":"","remote_ip":"::1","host":"localhost","method":"GET","uri":"/wc/gows","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36","status":200,"error":"","latency":39891800,"latency_human":"39.8918ms","bytes_in":0,"bytes_out":0}
2019/04/03 20:46:22 client readMsg c.hub.unregister now and c.conn.close
h.unregister Client deleted and close send
c.send not ok: []
2019/04/03 20:46:22 client writeMsg closing connection

Did I forget to add something here like a websocket dialer? Do I have to check for empty messages []? The rest of my code is exactly the same as you can see in the gorilla chat example.

RichardG

unread,
Apr 4, 2019, 7:10:45 AM4/4/19
to Gorilla web toolkit

Ok, removing defer ws.Close() keeps the connection alive and clients are able to connect and send messages. Unfortunately broadcasting to all clients doesn't work (anymore). Do I need to add a separate broadcasting handler?

Matt S

unread,
Apr 4, 2019, 8:21:49 AM4/4/19
to goril...@googlegroups.com
Your code diverges from the example app in multiple places, but critically:

• you create a Hub per-client-request in a handler, rather than at the top level of your application once - see 

Also - please open this as an issue on GitHub, much easier to handle code snippets & help you there!

--
You received this message because you are subscribed to the Google Groups "Gorilla web toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gorilla-web...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

RichardG

unread,
Apr 4, 2019, 9:07:53 AM4/4/19
to Gorilla web toolkit
Finally solved it! Was a bit more complicated than I thought it was.

Sorry Matt you are right. Next time I'll open an issue on github but I'm bit afraid that they will kill me  if I ask there (or elsewhere) due to the fact I'm a total newb in this topic (I'm glad someone answered here).

I'm so happy right now, you can't imagine. Struggling with this for so many hours, but every solved riddle is step more into getting the dream come true 8)

Solution: thanks to me adding println statements. I was able to figure out every time a client hits my rock solid golang echo server, a new hub has been created and every client had it's own hub ... uuups :D

What was to do? 1. Moving the hub into func main! (only need one hub at the moment)

hub := createHub()
go hub.run()

// func BuildEchoHosts() (hosts map[string]*Host) {}...
configuredHosts := BuildEchoHosts(hub)

2. Passing it to the webchat handler itself by extending the custom context! https://echo.labstack.com/guide/context

// CustomContext is for extending echo.Context
type CustomContext struct {
   echo.Context
   hub *Hub
}

3. Register middleware before any other middleware. In my context I use an self-written abstract echo host function:
func BuildEchoHosts(mainhub *Hub) (hosts map[string]*Host) {
// Make hub available to handlers by adding custom context
       tmpHost[subDomain].Use(func(h echo.HandlerFunc) echo.HandlerFunc {
           return func(c echo.Context) error {
               cc := &CustomContext{c, mainhub}
               return h(cc)
           }
       })
//...
}

4. Eventually I can now use 
cc := c.(*CustomContext)
hub := cc.hub

to reference it and passing to 
go handleWSRequests(hub, ws)

so I'm able to use only one hub :) 


Reply all
Reply to author
Forward
0 new messages