package main import ( "bufio" "fmt" "os" "time" "clickandjoin.app/serversenteventsserver/modules/cache" "clickandjoin.app/serversenteventsserver/modules/config" "clickandjoin.app/serversenteventsserver/modules/rabbitmq" "clickandjoin.app/serversenteventsserver/modules/structs" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/google/uuid" "github.com/sirupsen/logrus" "github.com/valyala/fasthttp" ) func init() { config.LoadConfig() if config.Cfg.Debug { logrus.SetLevel(logrus.DebugLevel) } logrus.Println("Debug:", config.Cfg.Debug) go rabbitmq.Init() } func main() { app := fiber.New() // wait so that rabbitmq can connect // TODO: better way to handle this time.Sleep(500 * time.Millisecond) if len(os.Args) < 2 { logrus.Fatalln("Please specify port") } // TODO: origin // CORS for external resources app.Use(cors.New(cors.Config{ AllowOrigins: "*", AllowHeaders: "Cache-Control", AllowCredentials: true, })) app.Get("/sse", func(c *fiber.Ctx) error { c.Set("Content-Type", "text/event-stream") c.Set("Cache-Control", "no-cache") c.Set("Connection", "keep-alive") c.Set("Transfer-Encoding", "chunked") c.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) { var sseclient structs.SSEClient sseclient.MessageChan = make(chan structs.SSEClientChanMessage) clientId := uuid.New() cache.SSEClients[clientId] = sseclient logrus.Debugln("NEW CLIENT ID:", clientId) logrus.Debugln(len(cache.SSEClients), "CLIENTS CONNECTED") for message := range sseclient.MessageChan { fmt.Fprintf(w, "data: %s\n\n", message.Message) 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. for id, sseClient := range cache.SSEClients { if id == message.ClientId { close(sseClient.MessageChan) delete(cache.SSEClients, id) logrus.Debugln("DELETE clientId:", id) } } } } })) return nil }) app.Listen("127.0.0.1:" + os.Args[1]) }