github.com/soypat/vectytemplater@v0.0.0-20220501050640-d40b24e35168/_templates/websocket-cli/todoserver.go (about) 1 package main 2 3 import ( 4 "context" 5 "log" 6 "net/http" 7 "time" 8 "vecty-templater-project/model" 9 10 "nhooyr.io/websocket" 11 "nhooyr.io/websocket/wsjson" 12 ) 13 14 type todoServer struct { 15 list []model.Item 16 } 17 18 // ServeHTTP is a basic websocket implementation for reading/writing a TODO list 19 // from a websocket. 20 func (s *todoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { 21 c, err := websocket.Accept(w, r, &websocket.AcceptOptions{ 22 Subprotocols: []string{model.WSSubprotocol}, 23 InsecureSkipVerify: true, 24 }) 25 if err != nil { 26 log.Println(err) 27 return 28 } 29 defer c.Close(websocket.StatusInternalError, "the sky is falling") 30 31 if c.Subprotocol() != model.WSSubprotocol { 32 c.Close(websocket.StatusPolicyViolation, "client must speak the "+model.WSSubprotocol+" subprotocol") 33 return 34 } 35 36 for { 37 err = s.getTODO(r.Context(), c) 38 if websocket.CloseStatus(err) == websocket.StatusNormalClosure { 39 return 40 } 41 42 if err != nil { 43 log.Printf("failed to echo with %v: %v\n", r.RemoteAddr, err) 44 return 45 } 46 } 47 } 48 49 // getTODO reads from the WebSocket connection and then writes 50 // the received message into the server's TODO list. 51 // The entire function has 200s to complete. 52 func (t *todoServer) getTODO(ctx context.Context, c *websocket.Conn) error { 53 ctx, cancel := context.WithTimeout(ctx, time.Second*200) 54 defer cancel() 55 reply := &model.ServerReply{ 56 Info: "I got the data!", 57 } 58 err := wsjson.Write(ctx, c, reply) 59 if err != nil { 60 return err 61 } 62 63 log.Printf("got TODO list:\n%s\n", t.list) 64 ctx, cancel = context.WithTimeout(ctx, time.Second*10) 65 defer cancel() 66 err = wsjson.Read(ctx, c, &t.list) 67 if err != nil { 68 return err 69 } 70 log.Println("data exchange succesful with reply: ", reply) 71 return nil 72 }