Skip to content

Instantly share code, notes, and snippets.

@Emyrk
Last active September 20, 2022 13:57
Show Gist options
  • Save Emyrk/95ca5b50cfd281e1c4f90e10d51a1831 to your computer and use it in GitHub Desktop.
Save Emyrk/95ca5b50cfd281e1c4f90e10d51a1831 to your computer and use it in GitHub Desktop.
Basic sse server in golang
package main
import (
"bytes"
"encoding/json"
"fmt"
"math/rand"
"net/http"
"time"
)
type Client struct {
name string
events chan *DashBoard
}
type DashBoard struct {
User uint
}
func main() {
mux := http.NewServeMux()
mux.Handle("/", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte(`
<!DOCTYPE html>
<div>
Hello World
</div>
<ul id="sse-list">
</ul>
<script>
// JS client
const source = new EventSource("/sse")
source.onmessage = (event) => {
console.log("OnMessage Called:")
console.log(event)
console.log(JSON.parse(event.data))
const li = document.createElement("li")
li.innerText = event.data
document.getElementById('sse-list').append(li);
}
</script>
`))
}))
mux.Handle("/js-copy", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte(`
<html>
<body>
<div id="content"></div>
<script type="text/javascript">
const source = new EventSource('/sse');
source.addEventListener('message', message => {
console.log('Got', message);
// Display the event data in the content div
document.querySelector('#content').innerHTML = event.data;
});
</script>
</body>
</html>
`))
}))
mux.Handle("/sse", http.HandlerFunc(dashboardHandler))
http.ListenAndServe(":3001", mux)
}
func dashboardHandler(w http.ResponseWriter, r *http.Request) {
client := &Client{name: r.RemoteAddr, events: make(chan *DashBoard, 10)}
go updateDashboard(client)
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
timeout := time.After(1 * time.Second)
select {
case ev := <-client.events:
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
enc.Encode(ev)
fmt.Fprintf(w, "data: %v\n\n", buf.String())
fmt.Printf("data: %v\n", buf.String())
case <-timeout:
fmt.Fprintf(w, ": nothing to sent\n\n")
}
if f, ok := w.(http.Flusher); ok {
f.Flush()
}
}
func updateDashboard(client *Client) {
for {
db := &DashBoard{
User: uint(rand.Uint32()),
}
client.events <- db
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment