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