Search code examples
gogorillago-swagger

How to serve websocket with go-swagger?


I'm trying to serve a chat websocket within my go-swagger API. I'm using this example: https://github.com/gorilla/websocket/tree/master/examples/chat

I tried attaching it to the http when the server starts, but after further reading I see that this can't work:

func configureServer(s *http.Server, scheme, addr string) {
  hub := chat.NewHub()

  go hub.Run()
  http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
    chat.ServeWs(hub, w, r)
  })
}

Then I tried using a custom server and changing server.Serve() to:

hub := chat.NewHub()
go hub.Run()

http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
  chat.ServeWs(hub, w, r)
})

if err := http.ListenAndServe(":8080", api.Serve(nil)); err != nil {
  log.Fatalln(err)
}

But also realized why this won't work.

Error during WebSocket handshake: Unexpected response code: 404

After some reading I'm starting to understand why the /ws was never found:

hub := chat.NewHub()
go hub.Run()

mux := http.NewServeMux()
mux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
  chat.ServeWs(hub, w, r)
})

server.SetHandler(mux)
if err := server.Serve(); err != nil {
  log.Fatalln(err)
}

Now the websockets works but the rest api doesn't, I can see why but I don't how to make both of them work. I'm fairly new to golang so i'm struggling with this.

How could I do that?

Thanks.


Solution

  • casualjim helped me at Github:

    You can put it in a middleware and hook it up in configure_XXX

    func mountWebSockets(next http.Handler) http.HandlerFunc {
       return func(w http.ResponseWriter, r *http.Request) {
           if r.URL.Path == "/ws" {
                chat.ServeWs(hub, w, r)
               return
           }
           next.ServeHTTP(w, r)
       }
    }
    

    Source: https://github.com/go-swagger/go-swagger/issues/2083#issuecomment-542764897