github.com/micro/go-micro/examples@v0.0.0-20210105173217-bf4ab679e18b/stream/web/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "io" 6 "log" 7 "net/http" 8 "time" 9 10 "github.com/gorilla/websocket" 11 proto "github.com/micro/go-micro/examples/stream/server/proto" 12 "github.com/micro/go-micro/v2/client" 13 "github.com/micro/go-micro/v2/web" 14 ) 15 16 var upgrader = websocket.Upgrader{ 17 CheckOrigin: func(r *http.Request) bool { return true }, 18 } 19 20 func Stream(cli proto.StreamerService, ws *websocket.Conn) error { 21 // Read initial request from websocket 22 var req proto.Request 23 err := ws.ReadJSON(&req) 24 if err != nil { 25 return err 26 } 27 28 // Even if we aren't expecting further requests from the websocket, we still need to read from it to ensure we 29 // get close signals 30 go func() { 31 for { 32 if _, _, err := ws.NextReader(); err != nil { 33 break 34 } 35 } 36 }() 37 38 log.Printf("Received Request: %v", req) 39 40 // Send request to stream server 41 stream, err := cli.ServerStream(context.Background(), &req) 42 if err != nil { 43 return err 44 } 45 defer stream.Close() 46 47 // Read from the stream server and pass responses on to websocket 48 for { 49 // Read from stream, end request once the stream is closed 50 rsp, err := stream.Recv() 51 if err != nil { 52 if err != io.EOF { 53 return err 54 } 55 56 break 57 } 58 59 // Write server response to the websocket 60 err = ws.WriteJSON(rsp) 61 if err != nil { 62 // End request if socket is closed 63 if isExpectedClose(err) { 64 log.Println("Expected Close on socket", err) 65 break 66 } else { 67 return err 68 } 69 } 70 } 71 72 return nil 73 } 74 75 func isExpectedClose(err error) bool { 76 if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) { 77 log.Println("Unexpected websocket close: ", err) 78 return false 79 } 80 81 return true 82 } 83 84 func main() { 85 // New web service 86 service := web.NewService( 87 web.Name("go.micro.web.stream"), 88 ) 89 90 if err := service.Init(); err != nil { 91 log.Fatal("Init", err) 92 } 93 94 // New RPC client 95 rpcClient := client.NewClient(client.RequestTimeout(time.Second * 120)) 96 cli := proto.NewStreamerService("go.micro.srv.stream", rpcClient) 97 98 // Serve static html/js 99 service.Handle("/", http.FileServer(http.Dir("html"))) 100 101 // Handle websocket connection 102 service.HandleFunc("/stream", func(w http.ResponseWriter, r *http.Request) { 103 // Upgrade request to websocket 104 conn, err := upgrader.Upgrade(w, r, nil) 105 if err != nil { 106 log.Fatal("Upgrade: ", err) 107 return 108 } 109 defer conn.Close() 110 111 // Handle websocket request 112 if err := Stream(cli, conn); err != nil { 113 log.Fatal("Echo: ", err) 114 return 115 } 116 log.Println("Stream complete") 117 }) 118 119 if err := service.Run(); err != nil { 120 log.Fatal("Run: ", err) 121 } 122 }