switched to SSE transport, seems to work

This commit is contained in:
Luxferre
2024-09-14 20:39:38 +03:00
parent 48dfb9c9f6
commit b76bc4f2d4
2 changed files with 59 additions and 5 deletions
+50 -5
View File
@@ -29,6 +29,7 @@ type ChatMessage struct {
var global_msg_id uint64 = 0 /* track global message ID */ var global_msg_id uint64 = 0 /* track global message ID */
var message_transport chan ChatMessage /* global message channel */ var message_transport chan ChatMessage /* global message channel */
var sse_transports []chan string /* SSE output channels */
var bro webview.WebView /* global browser instance handle */ var bro webview.WebView /* global browser instance handle */
/* escape HTML entities in JS parameters */ /* escape HTML entities in JS parameters */
@@ -50,12 +51,20 @@ func appendChatMessages() {
global_msg_id += 1 global_msg_id += 1
msg.Id = global_msg_id msg.Id = global_msg_id
/* directly call the append function on the JS side */ /* TODO any additional message logging should be done at this point! */
fmt_str := "gooseAppendMessage('%d', '%s', '%s', '%s', '%s', '%s');"
js := fmt.Sprintf(fmt_str, msg.Id, esc(msg.Type), esc(msg.Timestamp), esc(msg.Username), esc(msg.Text), esc(msg.Icon))
log.Printf("Evaluating JS: %s", js)
bro.Eval(js)
/* serialize the message and send it to the SSE channel */
json_msg, err := json.Marshal(msg)
if err != nil {
log.Println("Error serializing the message:", err)
}
/* broadcast the message across the clients */
for _, transport := range sse_transports {
if transport != nil {
transport <- string(json_msg)
}
}
} }
} }
@@ -73,6 +82,40 @@ func msgAddHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("{\"status\": 1}")) /* respond with a status */ w.Write([]byte("{\"status\": 1}")) /* respond with a status */
} }
/* GET /sse handler */
func sseHandler(w http.ResponseWriter, r *http.Request) {
/* prepare the headers */
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
w.Header().Set("Access-Control-Allow-Origin", "*")
/* create the channel */
transport := make(chan string)
/* append it to the broadcast list */
sse_transports = append(sse_transports, transport)
/* close the channel after exiting the function */
defer func() {
close(transport)
transport = nil
}()
/* use HTTP response flusher */
flusher, _ := w.(http.Flusher)
/* message loop */
for {
select {
case message := <-transport:
fmt.Fprintf(w, "data: %s\n\n", message)
flusher.Flush()
case <-r.Context().Done(): /* handle disconnects */
return
}
}
}
/* entry point */ /* entry point */
func main() { func main() {
config_path := "config.json" config_path := "config.json"
@@ -100,6 +143,8 @@ func main() {
go func() { /* start the server thread */ go func() { /* start the server thread */
/* serve the POST /new */ /* serve the POST /new */
http.HandleFunc("/new", msgAddHandler) http.HandleFunc("/new", msgAddHandler)
/* serve the GET /sse */
http.HandleFunc("/sse", sseHandler)
/* serve the webroot directory */ /* serve the webroot directory */
fs := http.FileServer(http.Dir("./webroot")) fs := http.FileServer(http.Dir("./webroot"))
http.Handle("/", fs) http.Handle("/", fs)
+9
View File
@@ -57,3 +57,12 @@ function gooseAppendMessage(id, type, timestamp, username, text, icon) {
/* autoscroll to the end */ /* autoscroll to the end */
window.scrollTo(0, document.body.scrollHeight) window.scrollTo(0, document.body.scrollHeight)
} }
/* entry point, set up an event source */
window.addEventListener('DOMContentLoaded', function() {
var msgSource = new EventSource('/sse')
msgSource.onmessage = e => {
var msg = JSON.parse(e.data)
gooseAppendMessage(msg.id, msg.type, msg.timestamp, msg.username, msg.text, msg.icon)
}
}, false)