Skip to content

Instantly share code, notes, and snippets.

@trusch
Created November 29, 2018 08:24
Show Gist options
  • Save trusch/b6366c8cf154ed036cf51b34e1d3fa26 to your computer and use it in GitHub Desktop.
Save trusch/b6366c8cf154ed036cf51b34e1d3fa26 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/sirupsen/logrus"
"golang.org/x/net/websocket"
)
type LogMessage struct {
Time time.Time `json:"time"`
Msg string `json:"msg"`
Stream string `json:"stream,omitempty"`
}
var (
logs = []LogMessage{
{
Time: time.Now(),
Msg: "msg1",
},
{
Time: time.Now(),
Msg: "msg2",
},
{
Time: time.Now(),
Msg: "msg3",
},
}
index = `
<!DOCTYPE html>
<html>
<head>
<title>event test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
// SSE handling
var evsrc = new EventSource("/get-logs?sse=true")
evsrc.onmessage = function (ev) {
var data = ev.data
$("#sse > ul").append("<li>" + data + "</li>")
}
evsrc.onerror = function (ev) {
evsrc.close()
}
// WebSocket handing
var ws = new WebSocket('ws://localhost:8080/get-logs?ws=true')
ws.onmessage = function (ev) {
var data = ev.data
$("#ws > ul").append("<li>" + data + "</li>")
}
ws.onerror = function () {
ws.close()
}
})
</script>
</head>
<body>
<h1>SSE test</h1>
<div id="sse">
<ul>
</ul>
</div>
<h1>WebSocket test</h1>
<div id="ws">
<ul>
</ul>
</div>
</body>
</html>
`
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(index))
})
http.HandleFunc("/get-logs", func(rw http.ResponseWriter, r *http.Request) {
useSSE := r.FormValue("sse")
if useSSE == "true" {
serveSSE(rw, r)
return
}
useWS := r.FormValue("ws")
if useWS == "true" {
serveWS(rw, r)
return
}
})
if err := http.ListenAndServe(":8080", nil); err != nil {
logrus.Fatal(err)
}
}
func serveSSE(rw http.ResponseWriter, r *http.Request) {
flusher, ok := rw.(http.Flusher)
if !ok {
http.Error(rw, "Streaming unsupported!", http.StatusInternalServerError)
return
}
rw.Header().Set("Content-Type", "text/event-stream")
rw.Header().Set("Cache-Control", "no-cache")
rw.Header().Set("Connection", "keep-alive")
for idx, log := range logs {
bs, err := json.Marshal(log)
if err != nil {
return
}
fmt.Fprintf(rw, "id:%v\ndata: %s\n\n", idx, string(bs))
flusher.Flush()
}
}
func serveWS(rw http.ResponseWriter, r *http.Request) {
streamLogs := func(ws *websocket.Conn) {
defer ws.Close()
for _, log := range logs {
bs, err := json.Marshal(log)
if err != nil {
return
}
ws.Write(bs)
}
}
websocket.Handler(streamLogs).ServeHTTP(rw, r)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment