87 lines
1.5 KiB
Go
87 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type Message struct {
|
|
Data interface{} `json:"data"`
|
|
Id string `json:"id"`
|
|
}
|
|
|
|
type Client struct {
|
|
Channel chan Message `json:"clients"`
|
|
}
|
|
|
|
var (
|
|
clients = make(map[*Client]bool)
|
|
clientsMutex sync.Mutex
|
|
broadcast = make(chan Message)
|
|
)
|
|
|
|
func SSEHandler(c *gin.Context) {
|
|
client := &Client{
|
|
Channel: make(chan Message),
|
|
}
|
|
|
|
log.Printf("events: %+v", client)
|
|
|
|
AddClient(client)
|
|
|
|
defer unregisterClient(client)
|
|
|
|
log.Printf("Client %s connected", client)
|
|
|
|
c.Writer.Header().Set("Content-Type", "text/event-stream")
|
|
c.Writer.Header().Set("Cache-Control", "no-cache")
|
|
c.Writer.Header().Set("Connection", "keep-alive")
|
|
c.Writer.Header().Set("Transfer-Encoding", "chunked")
|
|
|
|
for {
|
|
select {
|
|
case msg := <-client.Channel:
|
|
fmt.Fprintf(c.Writer, "data: %s\n\n", msg.Data)
|
|
c.Writer.Flush()
|
|
case <-c.Writer.CloseNotify():
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func AddClient(client *Client) {
|
|
clientsMutex.Lock()
|
|
clients[client] = true
|
|
clientsMutex.Unlock()
|
|
}
|
|
|
|
func unregisterClient(client *Client) {
|
|
clientsMutex.Lock()
|
|
delete(clients, client)
|
|
close(client.Channel)
|
|
clientsMutex.Unlock()
|
|
}
|
|
|
|
func SendMsg(c *gin.Context) {
|
|
var msg Message
|
|
c.ShouldBind(&msg)
|
|
msg.Id = time.Now().Format(time.RFC3339)
|
|
broadcast <- msg
|
|
c.JSON(http.StatusOK, gin.H{"status": "sent"})
|
|
}
|
|
|
|
func handleMessages() {
|
|
for {
|
|
msg := <-broadcast
|
|
clientsMutex.Lock()
|
|
for client := range clients {
|
|
client.Channel <- msg
|
|
}
|
|
clientsMutex.Unlock()
|
|
}
|
|
}
|