2020-05-08 00:49:00 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2020-05-08 00:49:00 +03:00
package eventsource
import (
"bytes"
"fmt"
"io"
"strings"
"time"
2021-03-02 00:08:10 +03:00
2021-07-24 19:03:58 +03:00
"code.gitea.io/gitea/modules/json"
2020-05-08 00:49:00 +03:00
)
2021-12-20 07:41:31 +03:00
func wrapNewlines ( w io . Writer , prefix , value [ ] byte ) ( sum int64 , err error ) {
2020-05-08 00:49:00 +03:00
if len ( value ) == 0 {
2023-07-07 08:31:56 +03:00
return 0 , nil
2020-05-08 00:49:00 +03:00
}
2022-06-20 13:02:49 +03:00
var n int
2020-05-08 00:49:00 +03:00
last := 0
for j := bytes . IndexByte ( value , '\n' ) ; j > - 1 ; j = bytes . IndexByte ( value [ last : ] , '\n' ) {
n , err = w . Write ( prefix )
sum += int64 ( n )
if err != nil {
2023-07-07 08:31:56 +03:00
return sum , err
2020-05-08 00:49:00 +03:00
}
n , err = w . Write ( value [ last : last + j + 1 ] )
sum += int64 ( n )
if err != nil {
2023-07-07 08:31:56 +03:00
return sum , err
2020-05-08 00:49:00 +03:00
}
last += j + 1
}
n , err = w . Write ( prefix )
sum += int64 ( n )
if err != nil {
2023-07-07 08:31:56 +03:00
return sum , err
2020-05-08 00:49:00 +03:00
}
n , err = w . Write ( value [ last : ] )
sum += int64 ( n )
if err != nil {
2023-07-07 08:31:56 +03:00
return sum , err
2020-05-08 00:49:00 +03:00
}
n , err = w . Write ( [ ] byte ( "\n" ) )
sum += int64 ( n )
2022-06-20 13:02:49 +03:00
return sum , err
2020-05-08 00:49:00 +03:00
}
// Event is an eventsource event, not all fields need to be set
type Event struct {
// Name represents the value of the event: tag in the stream
Name string
2023-07-04 21:36:08 +03:00
// Data is either JSONified []byte or any that can be JSONd
Data any
2020-05-08 00:49:00 +03:00
// ID represents the ID of an event
ID string
// Retry tells the receiver only to attempt to reconnect to the source after this time
Retry time . Duration
}
// WriteTo writes data to w until there's no more data to write or when an error occurs.
// The return value n is the number of bytes written. Any error encountered during the write is also returned.
func ( e * Event ) WriteTo ( w io . Writer ) ( int64 , error ) {
sum := int64 ( 0 )
2022-06-20 13:02:49 +03:00
var nint int
2020-05-08 00:49:00 +03:00
n , err := wrapNewlines ( w , [ ] byte ( "event: " ) , [ ] byte ( e . Name ) )
sum += n
if err != nil {
return sum , err
}
if e . Data != nil {
var data [ ] byte
switch v := e . Data . ( type ) {
case [ ] byte :
data = v
case string :
data = [ ] byte ( v )
default :
var err error
data , err = json . Marshal ( e . Data )
if err != nil {
return sum , err
}
}
n , err := wrapNewlines ( w , [ ] byte ( "data: " ) , data )
sum += n
if err != nil {
return sum , err
}
}
n , err = wrapNewlines ( w , [ ] byte ( "id: " ) , [ ] byte ( e . ID ) )
sum += n
if err != nil {
return sum , err
}
if e . Retry != 0 {
nint , err = fmt . Fprintf ( w , "retry: %d\n" , int64 ( e . Retry / time . Millisecond ) )
sum += int64 ( nint )
if err != nil {
return sum , err
}
}
nint , err = w . Write ( [ ] byte ( "\n" ) )
sum += int64 ( nint )
return sum , err
}
func ( e * Event ) String ( ) string {
buf := new ( strings . Builder )
_ , _ = e . WriteTo ( buf )
return buf . String ( )
}