Created
October 31, 2022 06:13
-
-
Save schadokar/8763dafd6d22f1d514383cc9a071d4a4 to your computer and use it in GitHub Desktop.
gochatapp websocket.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ws | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"net/http" | |
"time" | |
"gochatapp/model" | |
"gochatapp/pkg/redisrepo" | |
"github.com/gorilla/websocket" | |
) | |
type Client struct { | |
Conn *websocket.Conn | |
Username string | |
} | |
type Message struct { | |
Type string `json:"type"` | |
User string `json:"user,omitempty"` | |
Chat model.Chat `json:"chat,omitempty"` | |
} | |
var clients = make(map[*Client]bool) | |
var broadcast = make(chan *model.Chat) | |
// We'll need to define an Upgrader | |
// this will require a Read and Write buffer size | |
var upgrader = websocket.Upgrader{ | |
ReadBufferSize: 1024, | |
WriteBufferSize: 1024, | |
// We'll need to check the origin of our connection | |
// this will allow us to make requests from our React | |
// development server to here. | |
// For now, we'll do no checking and just allow any connection | |
CheckOrigin: func(r *http.Request) bool { return true }, | |
} | |
// define a receiver which will listen for | |
// new messages being sent to our WebSocket | |
// endpoint | |
func receiver(client *Client) { | |
for { | |
// read in a message | |
// readMessage returns messageType, message, err | |
// messageType: 1-> Text Message, 2 -> Binary Message | |
_, p, err := client.Conn.ReadMessage() | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
m := &Message{} | |
err = json.Unmarshal(p, m) | |
if err != nil { | |
log.Println("error while unmarshaling chat", err) | |
continue | |
} | |
fmt.Println("host", client.Conn.RemoteAddr()) | |
if m.Type == "bootup" { | |
// do mapping on bootup | |
client.Username = m.User | |
fmt.Println("client successfully mapped", &client, client, client.Username) | |
} else { | |
fmt.Println("received message", m.Type, m.Chat) | |
c := m.Chat | |
c.Timestamp = time.Now().Unix() | |
// save in redis | |
id, err := redisrepo.CreateChat(&c) | |
if err != nil { | |
log.Println("error while saving chat in redis", err) | |
return | |
} | |
c.ID = id | |
broadcast <- &c | |
} | |
} | |
} | |
func broadcaster() { | |
for { | |
message := <-broadcast | |
// send to every client that is currently connected | |
fmt.Println("new message", message) | |
for client := range clients { | |
// send message only to involved users | |
fmt.Println("username:", client.Username, | |
"from:", message.From, | |
"to:", message.To) | |
if client.Username == message.From || client.Username == message.To { | |
err := client.Conn.WriteJSON(message) | |
if err != nil { | |
log.Printf("Websocket error: %s", err) | |
client.Conn.Close() | |
delete(clients, client) | |
} | |
} | |
} | |
} | |
} | |
// define our WebSocket endpoint | |
func serveWs(w http.ResponseWriter, r *http.Request) { | |
fmt.Println(r.Host, r.URL.Query()) | |
// upgrade this connection to a WebSocket | |
// connection | |
ws, err := upgrader.Upgrade(w, r, nil) | |
if err != nil { | |
log.Println(err) | |
} | |
client := &Client{Conn: ws} | |
// register client | |
clients[client] = true | |
fmt.Println("clients", len(clients), clients, ws.RemoteAddr()) | |
// listen indefinitely for new messages coming | |
// through on our WebSocket connection | |
receiver(client) | |
fmt.Println("exiting", ws.RemoteAddr().String()) | |
delete(clients, client) | |
} | |
func setupRoutes() { | |
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprintf(w, "Simple Server") | |
}) | |
// map our `/ws` endpoint to the `serveWs` function | |
http.HandleFunc("/ws", serveWs) | |
} | |
func StartWebsocketServer() { | |
redisClient := redisrepo.InitialiseRedis() | |
defer redisClient.Close() | |
go broadcaster() | |
setupRoutes() | |
http.ListenAndServe(":8081", nil) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment