|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"html/template"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type handler = func(http.ResponseWriter, *http.Request)
|
|
|
|
|
|
|
|
func generateHandler(file string, handler func(), data func() any) handler {
|
|
|
|
tmpl := template.Must(template.ParseFiles(fmt.Sprintf("templates/%s", file)))
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
handler()
|
|
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
|
|
tmpl.Execute(w, data())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateClick() handler {
|
|
|
|
var clicks uint = 0
|
|
|
|
return generateHandler(
|
|
|
|
"click.html",
|
|
|
|
func() { clicks++ },
|
|
|
|
func() any { return clicks },
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateSseHandler(handler func(http.ResponseWriter, *http.Request)) handler {
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Header().Set("Content-Type", "text/event-stream")
|
|
|
|
w.Header().Set("Cache-Control", "no-cache")
|
|
|
|
w.Header().Set("Connection", "keep-alive")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
handler(w, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateCounter() handler {
|
|
|
|
return generateSseHandler(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
tick := time.Tick(500 * time.Millisecond)
|
|
|
|
ctx := r.Context()
|
|
|
|
outer:
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
break outer
|
|
|
|
case <-tick:
|
|
|
|
fmt.Fprintf(w, "event: count\ndata: <div>%d</div>\n\n", i)
|
|
|
|
w.(http.Flusher).Flush()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
http.Handle("/", http.FileServer(http.Dir("static")))
|
|
|
|
http.HandleFunc("/api/click1", generateClick())
|
|
|
|
http.HandleFunc("/api/click2", generateClick())
|
|
|
|
http.HandleFunc("/api/click3", generateClick())
|
|
|
|
http.HandleFunc("/api/counter", generateCounter())
|
|
|
|
log.Fatal(http.ListenAndServe(":3333", nil))
|
|
|
|
}
|