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.

event.go 2.4KB

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