main.go
:
package main
import (
"fmt"
"net/http"
"time"
)
var indexHtml = `<!DOCTYPE html>
<html>
<body>
<h1>SSE Messages</h1>
<button id="stop">Stop</button>
<div id="debug"></div>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
let source = new EventSource("sse");
document.getElementById("stop").onclick = function(event) {
source.close();
};
source.onopen = function(event) {
document.getElementById("debug").innerHTML += "Connection to server opened.<br>";
};
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
source.onerror = function(event) {
document.getElementById("debug").innerHTML += "EventSource failed.<br>";
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
`
func index(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(indexHtml))
}
func sse(w http.ResponseWriter, req *http.Request) {
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Server does not support Flusher!",
http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("X-Accel-Buffering", "no")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
w.Header().Set("Transfer-Encoding", "chunked")
w.WriteHeader(http.StatusOK)
i := 0
for {
i++
// Also note that when using SSE, you should "pack" updates into SSE frames,
// that is you should start them with "data:" prefix, and end each frame with 2 newline chars: "\n\n".
s := fmt.Sprintf("data:%d sending\n\n", i)
fmt.Print(s)
_, err := w.Write([]byte(s))
if err != nil {
fmt.Println("Client closed.")
break
}
flusher.Flush()
time.Sleep(1 * time.Second)
}
}
func main() {
http.HandleFunc("/", index)
http.HandleFunc("/sse", sse)
panic(http.ListenAndServe(":8080", nil))
}