2 Commits 4de0d35aee ... 583ae2ce4e

Author SHA1 Message Date
  Gildas Chabot 583ae2ce4e add implementation with server sent events 6 years ago
  Gildas Chabot dd234f9e2c add implementation with websockets 6 years ago
2 changed files with 145 additions and 0 deletions
  1. 45 0
      index.html
  2. 100 0
      ms.go

+ 45 - 0
index.html

@@ -0,0 +1,45 @@
1
+<html>
2
+  <head>
3
+  </head>
4
+  <body>
5
+      <div>
6
+          <h2>Websocket</h2>
7
+          <p>Progress: <span id="websocket"></span></p>
8
+          <button onclick="websocket()">Listen</button>
9
+      </div>
10
+
11
+      <div>
12
+          <h2>Server Sent Event</h2>
13
+          <p>Progress: <span id="sse"></span></p>
14
+          <button onclick="sse()">Listen</button>
15
+      </div>
16
+
17
+      <script>
18
+       function websocket() {
19
+         var socket = new WebSocket({{ .websocket }}, "protocolOne");
20
+         socket.onmessage = function (event) {
21
+           if (event.data === "100") {
22
+             document.getElementById("websocket").innerHTML = "done!";
23
+             socket.close();
24
+             return;
25
+           }
26
+           document.getElementById("websocket").innerHTML=event.data+"%";
27
+         };
28
+       }
29
+
30
+       function sse() {
31
+         document.getElementById("sse").innerHTML = "done!";
32
+         var source = new EventSource({{ .sse }});
33
+         source.onmessage = function(event) {
34
+           console.log("truc");
35
+           if (event.data === "100") {
36
+             document.getElementById("sse").innerHTML = "done!";
37
+             source.close();
38
+             return;
39
+           }
40
+           document.getElementById("sse").innerHTML=event.data+"%";
41
+         };
42
+       }
43
+      </script>
44
+  </body>
45
+</html>

+ 100 - 0
ms.go

@@ -0,0 +1,100 @@
1
+package main
2
+
3
+import (
4
+	"io"
5
+	"math/rand"
6
+	"net/http"
7
+	"os"
8
+	"strconv"
9
+	"time"
10
+
11
+	"github.com/gin-gonic/gin"
12
+	"github.com/gorilla/websocket"
13
+)
14
+
15
+func main() {
16
+	port := "8080"
17
+	if os.Getenv("PORT") != "" {
18
+		port = os.Getenv("PORT")
19
+	}
20
+
21
+	rand.Seed(time.Now().Unix())
22
+
23
+	router := gin.Default()
24
+
25
+	router.LoadHTMLFiles("index.html")
26
+
27
+	router.GET("/", func(c *gin.Context) {
28
+		c.HTML(http.StatusOK, "index.html", gin.H{
29
+			"websocket": "ws://localhost:" + port + "/ws",
30
+			"sse":       "http://localhost:" + port + "/sse",
31
+		})
32
+	})
33
+	router.GET("/ws", websocketHandler(websocket.Upgrader{
34
+		Subprotocols: []string{"protocolOne"},
35
+	}))
36
+	router.GET("/sse", serverSentEventHandler())
37
+
38
+	router.Run(":" + port)
39
+}
40
+
41
+func websocketHandler(upgrader websocket.Upgrader) func(c *gin.Context) {
42
+	return func(c *gin.Context) {
43
+		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
44
+		if err != nil {
45
+			c.AbortWithError(http.StatusInternalServerError, err)
46
+			return
47
+		}
48
+
49
+		t := task{}
50
+		t.start()
51
+		for {
52
+			progress, ok := <-t.progress
53
+			if !ok {
54
+				break
55
+			}
56
+
57
+			if err := conn.WriteMessage(1, []byte(strconv.Itoa(progress))); err != nil {
58
+				c.AbortWithError(http.StatusInternalServerError, err)
59
+				return
60
+			}
61
+		}
62
+	}
63
+}
64
+
65
+func serverSentEventHandler() func(c *gin.Context) {
66
+	return func(c *gin.Context) {
67
+		t := task{}
68
+		t.start()
69
+
70
+		c.Stream(func(w io.Writer) bool {
71
+			progress, ok := <-t.progress
72
+			if !ok {
73
+				return false
74
+			}
75
+
76
+			c.SSEvent("", strconv.Itoa(progress))
77
+			return true
78
+		})
79
+	}
80
+}
81
+
82
+type task struct {
83
+	progress chan int
84
+}
85
+
86
+func (t *task) start() {
87
+	t.progress = make(chan int)
88
+	go func() {
89
+		p := 0
90
+		t.progress <- p
91
+		for p < 100 {
92
+			if rand.Intn(100) > 50 {
93
+				p++
94
+				t.progress <- p
95
+			}
96
+			time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
97
+		}
98
+		close(t.progress)
99
+	}()
100
+}