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  }