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  }