go.sum
go.sum
This is a binary file and will not be displayed.
+19
main.go
+19
main.go
···
1
+
package main
2
+
3
+
import (
4
+
"log"
5
+
"net/http"
6
+
)
7
+
8
+
func main() {
9
+
pubsub := NewPubSub()
10
+
11
+
r := &http.ServeMux{}
12
+
r.HandleFunc("GET /subscribe", pubsub.HandleSubscribe)
13
+
r.HandleFunc("POST /publish", pubsub.HandlePublish)
14
+
15
+
server := http.Server{Addr: ":8000", Handler: r}
16
+
if err := server.ListenAndServe(); err != nil {
17
+
log.Fatal(err)
18
+
}
19
+
}
+62
pubsub.go
+62
pubsub.go
···
1
+
package main
2
+
3
+
import (
4
+
"encoding/json"
5
+
"fmt"
6
+
"net/http"
7
+
"time"
8
+
)
9
+
10
+
type PubSub struct {
11
+
channel chan string
12
+
}
13
+
14
+
func NewPubSub() *PubSub {
15
+
return &PubSub{channel: make(chan string)}
16
+
}
17
+
18
+
func (p *PubSub) HandleSubscribe(w http.ResponseWriter, r *http.Request) {
19
+
w.Header().Set("Content-Type", "text/event-stream")
20
+
w.Header().Set("Connection", "keep-alive")
21
+
w.Header().Set("Cache-Control", "no-cache")
22
+
23
+
clientGone := r.Context().Done()
24
+
25
+
rc := http.NewResponseController(w)
26
+
for {
27
+
select {
28
+
case <-clientGone:
29
+
fmt.Println("Client disconnected")
30
+
return
31
+
case data := <- p.channel:
32
+
_, err := fmt.Fprintf(w, "data: %s\n", data)
33
+
if err != nil {
34
+
return
35
+
}
36
+
if err = rc.Flush(); err != nil {
37
+
return
38
+
}
39
+
time.Sleep(time.Second)
40
+
}
41
+
}
42
+
}
43
+
44
+
type Input struct {
45
+
Value uint `json:"value"`
46
+
Name string `json:"name"`
47
+
}
48
+
49
+
func (p *PubSub) HandlePublish(w http.ResponseWriter, r *http.Request) {
50
+
var input Input
51
+
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
52
+
http.Error(w, err.Error(), http.StatusBadRequest)
53
+
return
54
+
}
55
+
56
+
p.channel <- fmt.Sprintf("%+v", input)
57
+
58
+
w.Header().Set("Content-Type", "application/json")
59
+
w.WriteHeader(http.StatusOK)
60
+
w.Write([]byte("Message received"))
61
+
}
62
+