mirror of
https://github.com/chaitin/MonkeyCode.git
synced 2026-02-02 06:43:23 +08:00
86 lines
2.5 KiB
Go
86 lines
2.5 KiB
Go
package sse
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// Event represents Server-Sent Event.
|
|
// SSE explanation: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format
|
|
type Event struct {
|
|
// ID is used to set the EventSource object's last event ID value.
|
|
ID []byte
|
|
// Data field is for the message. When the EventSource receives multiple consecutive lines
|
|
// that begin with data:, it concatenates them, inserting a newline character between each one.
|
|
// Trailing newlines are removed.
|
|
Data []byte
|
|
// Event is a string identifying the type of event described. If this is specified, an event
|
|
// will be dispatched on the browser to the listener for the specified event name; the website
|
|
// source code should use addEventListener() to listen for named events. The onmessage handler
|
|
// is called if no event name is specified for a message.
|
|
Event []byte
|
|
// Retry is the reconnection time. If the connection to the server is lost, the browser will
|
|
// wait for the specified time before attempting to reconnect. This must be an integer, specifying
|
|
// the reconnection time in milliseconds. If a non-integer value is specified, the field is ignored.
|
|
Retry []byte
|
|
// Comment line can be used to prevent connections from timing out; a server can send a comment
|
|
// periodically to keep the connection alive.
|
|
Comment []byte
|
|
}
|
|
|
|
// MarshalTo marshals Event to given Writer
|
|
func (ev *Event) MarshalTo(w io.Writer) error {
|
|
// Marshalling part is taken from: https://github.com/r3labs/sse/blob/c6d5381ee3ca63828b321c16baa008fd6c0b4564/http.go#L16
|
|
if len(ev.Data) == 0 && len(ev.Comment) == 0 {
|
|
return nil
|
|
}
|
|
|
|
if len(ev.Data) > 0 {
|
|
if _, err := fmt.Fprintf(w, "id: %s\n", ev.ID); err != nil {
|
|
return err
|
|
}
|
|
|
|
sd := bytes.Split(ev.Data, []byte("\n"))
|
|
for i := range sd {
|
|
if _, err := fmt.Fprintf(w, "data: %s\n", sd[i]); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if len(ev.Event) > 0 {
|
|
if _, err := fmt.Fprintf(w, "event: %s\n", ev.Event); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if len(ev.Retry) > 0 {
|
|
if _, err := fmt.Fprintf(w, "retry: %s\n", ev.Retry); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(ev.Comment) > 0 {
|
|
if _, err := fmt.Fprintf(w, ": %s\n", ev.Comment); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if _, err := fmt.Fprint(w, "\n"); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func WriteEvent(w io.Writer, data []byte) error {
|
|
ev := &Event{
|
|
ID: []byte(uuid.New().String()),
|
|
Data: data,
|
|
}
|
|
return ev.MarshalTo(w)
|
|
}
|