I have a SSE
endpoint which sends data to the frontend, and that data is retrieved from another API
endpoint. I'm still quite new with channels
in go
and it seems that i have to trigger the API endpoint twice so that the SSE endpoint will send the data once to the frontend. As for now, i have not written the frontend code to establish the SSE connection since I'm still playing around with channels. Could someone explain why this requires the API to be called twice for the SSE to send data?
The SSE route
func SendSSE(appCtx *fiber.Ctx, dataChannel chan string) error {
appCtx.Set("Content-Type", "text/event-stream")
appCtx.Set("Cache-Control", "no-cache")
appCtx.Set("Connection", "keep-alive")
appCtx.Set("Transfer-Encoding", "chunked")
appCtx.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
log.Println("SSE Opened")
for {
log.Println("Retrieving data channel..")
fmt.Fprintf(w, "data: Message: %s\n\n", <-dataChannel)
log.Println(<-dataChannel)
err := w.Flush()
if err != nil {
// Refreshing page in web browser will establish a new
// SSE connection, but only (the last) one is alive, so
// dead connections must be closed here.
fmt.Printf("Error while flushing: %v. Closing http connection.\n", err)
break
}
}
}))
fmt.Println("SSE Closed")
return nil
}
API that sends data to sse
func GetApiData(appCtx *fiber.Ctx, dataChannel chan string) error {
log.Println("Sending DataChannel data")
dataChannel <- "Data is passed from api to sse"
return appCtx.Status(http.StatusOK).SendString("Not Implemented")
}
The reason you see this is that you are consuming 2 messages in this section
fmt.Fprintf(w, "data: Message: %s\n\n", <-dataChannel)
log.Println(<-dataChannel)
Every odd message will get sent to SSE, every even message will be logged to the console. It should be changed to
message := <-dataChannel
fmt.Fprintf(w, "data: Message: %s\n\n", message)
log.Println(message)