go sse

卓能文發表於2024-07-25

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))
}

相關文章