package main import ( "encoding/json" "fmt" "github.com/brianvoe/gofakeit/v6" "github.com/gorilla/websocket" log "github.com/sirupsen/logrus" "net/http" "time" ) // We'll need to define an upgradeToWs // this will require a Read and Write buffer size var upgradeToWs = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } func apiV1WebSocketHandler(w http.ResponseWriter, r *http.Request) { upgradeToWs.CheckOrigin = func(r *http.Request) bool { return true } ws, err := upgradeToWs.Upgrade(w, r, nil) if err != nil { log.Println("cannot upgrade websocket", err) return } // helpful log statement to show connections log.Println("Websocket Api/V1: Client Connected", r.RemoteAddr) wsReader(ws) } func wsReader(conn *websocket.Conn) { wsq.addConnection(conn) for { stillExist := wsq.has(conn) if !stillExist { return // the connection has been removed. } // read in a message messageType, p, err := conn.ReadMessage() if err != nil { wsq.del(conn) log.Println(err) return } // WsEchoIncomingMessage(conn, string(p), messageType) switch messageType { case websocket.TextMessage: WsProcessingTxtMessage(conn, string(p)) break case websocket.BinaryMessage: WsProcessingBinaryMessage(conn, p) break case websocket.PingMessage: break case websocket.PongMessage: break } } } func WsProcessingTxtMessage(conn *websocket.Conn, str string) { if str == "send dummy string for 500 times" { go wsDummySender(conn) } // must be json message with key, value pairs incoming := make(map[string]string) e := json.Unmarshal([]byte(str), &incoming) if e != nil { log.Error("ws incoming msg error not json", str, e) return } key := incoming["t"] for _, v := range apiV1WsHandler { if key == v.Keyword { v.Handler(conn, incoming) return // we have already processed } } } func WsProcessingBinaryMessage(conn *websocket.Conn, data []byte) { return } func WsEchoIncomingMessage(conn *websocket.Conn, msg string, messageType int) { // print out that message for clarity fmt.Println(msg) // this is echo if err := conn.WriteMessage(messageType, []byte(msg)); err != nil { wsq.del(conn) log.Println(err) return } } func WsBroadCast(msg string) { wsq.wsDoBroadcast(msg, "") } func WsSend(To string, msg map[string]string) { b, e := json.Marshal(msg) if e != nil { log.Error("cannot broadcast websocket message, cannot convert to json", msg) } conn := wsq.getConnBySessionId(To) if conn != nil { err := conn.WriteMessage(websocket.TextMessage, b) if err != nil { wsq.del(conn) } } } func WsBroadCastExceptMe(me string, msg map[string]string) { b, e := json.Marshal(msg) if e == nil { wsq.wsDoBroadcast(string(b), me) } } func wsDummySender(conn *websocket.Conn) { //write subsequent 5 copies, each after 1 second log.Info("start sending server data to client ..") p := "dummy string from server " for i := 1; i < 500; i++ { time.Sleep(1 * time.Second) //msg := fmt.Sprintf("copy %d, %s, %s", i, p, wsDummyString()) // 4M long string no issue msg := fmt.Sprintf("copy %d, %s ", i, p) log.Info("dummy sender is working, ", msg) if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil { log.Println("wsDummySender stopped on error: ", err) return } } } func wsDummyString() string { s := gofakeit.LetterN(4096000) // 4M return s }