server.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package sse
  2. import (
  3. "github.com/gin-gonic/gin"
  4. "io"
  5. "net/http"
  6. "sync"
  7. "sync/atomic"
  8. )
  9. type clientChan struct {
  10. User string
  11. Chan chan msgChan
  12. }
  13. type msgChan struct {
  14. Name string
  15. Message string
  16. }
  17. type Event struct {
  18. SessionList sync.Map
  19. Count atomic.Int32
  20. Register chan clientChan
  21. Unregister chan string
  22. }
  23. func NewServer() (event *Event) {
  24. event = &Event{
  25. SessionList: sync.Map{},
  26. Count: atomic.Int32{},
  27. Register: make(chan clientChan),
  28. Unregister: make(chan string),
  29. }
  30. go event.listen()
  31. return
  32. }
  33. func (stream *Event) listen() {
  34. for {
  35. select {
  36. case client := <-stream.Register:
  37. stream.SessionList.Store(client.User, client.Chan)
  38. stream.Count.Add(1)
  39. case user := <-stream.Unregister:
  40. value, ok := stream.SessionList.Load(user)
  41. if ok {
  42. event := value.(chan msgChan)
  43. close(event)
  44. stream.SessionList.Delete(user)
  45. stream.Count.Add(-1)
  46. }
  47. }
  48. }
  49. }
  50. func (stream *Event) HandlerFunc(auth func(c *gin.Context) (string, error)) gin.HandlerFunc {
  51. return func(c *gin.Context) {
  52. user, err := auth(c)
  53. if err != nil {
  54. c.AbortWithStatus(http.StatusBadRequest)
  55. return
  56. }
  57. event := make(chan msgChan)
  58. client := clientChan{
  59. User: user,
  60. Chan: event,
  61. }
  62. stream.Register <- client
  63. defer func() {
  64. stream.Unregister <- user
  65. }()
  66. c.Writer.Header().Set("Content-Type", "text/event-stream")
  67. c.Writer.Header().Set("Cache-Control", "no-cache")
  68. c.Writer.Header().Set("Connection", "keep-alive")
  69. c.Writer.Header().Set("Transfer-Encoding", "chunked")
  70. c.Stream(func(w io.Writer) bool {
  71. if msg, ok := <-event; ok {
  72. c.SSEvent(msg.Name, msg.Message)
  73. return true
  74. }
  75. return false
  76. })
  77. c.Next()
  78. }
  79. }
  80. func (stream *Event) Push(user, name, msg string) bool {
  81. value, ok := stream.SessionList.Load(user)
  82. if ok {
  83. val := value.(chan msgChan)
  84. val <- msgChan{Name: name, Message: msg}
  85. }
  86. return false
  87. }
  88. func (stream *Event) Broadcast(name, msg string) {
  89. stream.SessionList.Range(func(user, value any) bool {
  90. val := value.(chan msgChan)
  91. val <- msgChan{Name: name, Message: msg}
  92. return true
  93. })
  94. }