You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
2.4 KiB

  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package eventsource
  5. import (
  6. "bytes"
  7. "encoding/json"
  8. "fmt"
  9. "io"
  10. "strings"
  11. "time"
  12. )
  13. func wrapNewlines(w io.Writer, prefix []byte, value []byte) (sum int64, err error) {
  14. if len(value) == 0 {
  15. return
  16. }
  17. n := 0
  18. last := 0
  19. for j := bytes.IndexByte(value, '\n'); j > -1; j = bytes.IndexByte(value[last:], '\n') {
  20. n, err = w.Write(prefix)
  21. sum += int64(n)
  22. if err != nil {
  23. return
  24. }
  25. n, err = w.Write(value[last : last+j+1])
  26. sum += int64(n)
  27. if err != nil {
  28. return
  29. }
  30. last += j + 1
  31. }
  32. n, err = w.Write(prefix)
  33. sum += int64(n)
  34. if err != nil {
  35. return
  36. }
  37. n, err = w.Write(value[last:])
  38. sum += int64(n)
  39. if err != nil {
  40. return
  41. }
  42. n, err = w.Write([]byte("\n"))
  43. sum += int64(n)
  44. return
  45. }
  46. // Event is an eventsource event, not all fields need to be set
  47. type Event struct {
  48. // Name represents the value of the event: tag in the stream
  49. Name string
  50. // Data is either JSONified []byte or interface{} that can be JSONd
  51. Data interface{}
  52. // ID represents the ID of an event
  53. ID string
  54. // Retry tells the receiver only to attempt to reconnect to the source after this time
  55. Retry time.Duration
  56. }
  57. // WriteTo writes data to w until there's no more data to write or when an error occurs.
  58. // The return value n is the number of bytes written. Any error encountered during the write is also returned.
  59. func (e *Event) WriteTo(w io.Writer) (int64, error) {
  60. sum := int64(0)
  61. nint := 0
  62. n, err := wrapNewlines(w, []byte("event: "), []byte(e.Name))
  63. sum += n
  64. if err != nil {
  65. return sum, err
  66. }
  67. if e.Data != nil {
  68. var data []byte
  69. switch v := e.Data.(type) {
  70. case []byte:
  71. data = v
  72. case string:
  73. data = []byte(v)
  74. default:
  75. var err error
  76. data, err = json.Marshal(e.Data)
  77. if err != nil {
  78. return sum, err
  79. }
  80. }
  81. n, err := wrapNewlines(w, []byte("data: "), data)
  82. sum += n
  83. if err != nil {
  84. return sum, err
  85. }
  86. }
  87. n, err = wrapNewlines(w, []byte("id: "), []byte(e.ID))
  88. sum += n
  89. if err != nil {
  90. return sum, err
  91. }
  92. if e.Retry != 0 {
  93. nint, err = fmt.Fprintf(w, "retry: %d\n", int64(e.Retry/time.Millisecond))
  94. sum += int64(nint)
  95. if err != nil {
  96. return sum, err
  97. }
  98. }
  99. nint, err = w.Write([]byte("\n"))
  100. sum += int64(nint)
  101. return sum, err
  102. }
  103. func (e *Event) String() string {
  104. buf := new(strings.Builder)
  105. _, _ = e.WriteTo(buf)
  106. return buf.String()
  107. }