heruvym/internal/tools/tools.go

90 lines
1.9 KiB
Go
Raw Normal View History

2021-05-01 10:05:45 +00:00
package tools
import (
2024-10-01 11:34:09 +00:00
"bufio"
2021-05-01 10:05:45 +00:00
"context"
"fmt"
2024-10-01 11:34:09 +00:00
"github.com/gofiber/fiber/v2"
2021-05-01 10:05:45 +00:00
"net/http"
"time"
)
2021-05-01 12:36:22 +00:00
type DataEmitter func(ctx context.Context) chan interface{}
2021-05-01 10:05:45 +00:00
2021-05-02 22:25:12 +00:00
const ContextURLKey = "url"
2021-05-01 10:05:45 +00:00
2024-10-01 11:34:09 +00:00
func SseWrapper(emitter DataEmitter) fiber.Handler {
return func(ctx *fiber.Ctx) error {
2022-02-27 15:27:44 +00:00
defer func() {
if v := recover(); v != nil {
fmt.Println("sse her err", v)
}
2022-11-02 18:52:02 +00:00
}()
2021-05-15 14:03:10 +00:00
// Отправляем header event-stream
2024-02-20 18:43:12 +00:00
fmt.Println("SseWrapper")
2021-05-15 14:03:10 +00:00
2024-10-01 11:34:09 +00:00
ctx.Set("Content-Type", "text/event-stream")
ctx.Set("Cache-Control", "no-cache")
ctx.Set("Connection", "keep-alive")
2021-05-15 14:03:10 +00:00
2024-10-01 11:34:09 +00:00
ctxValue := context.WithValue(ctx.Context(), ContextURLKey, ctx.Query("ticket"))
ctxCancel, cancel := context.WithCancel(ctxValue)
2021-05-01 10:05:45 +00:00
2024-10-01 11:34:09 +00:00
dE := emitter(ctxCancel)
2021-09-05 15:24:13 +00:00
if dE == nil {
2024-02-20 18:43:12 +00:00
fmt.Println("dE")
2024-10-01 11:34:09 +00:00
cancel()
return ctx.Status(fiber.StatusUnauthorized).SendString("no token")
2021-09-05 15:24:13 +00:00
}
2024-10-01 13:15:39 +00:00
ctx.Context().SetBodyStreamWriter(func(w *bufio.Writer) {
2024-10-01 11:34:09 +00:00
pingTicker := time.NewTicker(5 * time.Second)
defer pingTicker.Stop()
defer close(dE)
for {
select {
case <-pingTicker.C:
fmt.Fprintf(w, "data: %s\n\n", `{"event": "ping"}`)
if err := w.Flush(); err != nil {
fmt.Println("sse, close connection")
cancel()
return
}
case m := <-dE:
if m == nil {
continue
}
if err, ok := m.(error); ok {
fmt.Fprintf(w, "data: %s\n\n", err.Error())
if err := w.Flush(); err != nil {
fmt.Println("error flushing err ")
cancel()
return
}
}
fmt.Fprintf(w, "data: %s\n\n", m)
if err := w.Flush(); err != nil {
fmt.Println("error flushing data")
cancel()
return
2021-05-15 20:10:07 +00:00
}
2021-05-02 22:25:12 +00:00
}
}
2024-10-01 11:34:09 +00:00
})
return nil
2021-05-01 10:05:45 +00:00
}
}
// Sends SSE ping
func SSEPing(w http.ResponseWriter) {
if _, err := w.Write([]byte(":ping\n\n")); err != nil {
panic(err)
}
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
} else {
panic("streaming unsupported")
}
}