package main import ( "bufio" "encoding/json" "io" "strings" ) // sseReader parses a text/event-stream into a sequence of JSON events. // Each event is one or more "data: " lines; the lines are concatenated // and parsed as a single JSON object. Blank lines separate events. type sseReader struct { r *bufio.Reader } func newSSEReader(r io.Reader) *sseReader { return &sseReader{r: bufio.NewReader(r)} } func (s *sseReader) next() (map[string]any, error) { var data strings.Builder for { line, err := s.r.ReadString('\n') if err != nil { if err == io.EOF && data.Len() > 0 { return parseEvent(data.String()) } return nil, err } line = strings.TrimRight(line, "\r\n") if line == "" { if data.Len() > 0 { return parseEvent(data.String()) } continue // blank line, no event buffered yet } if strings.HasPrefix(line, "data: ") { data.WriteString(strings.TrimPrefix(line, "data: ")) } else if strings.HasPrefix(line, "data:") { data.WriteString(strings.TrimPrefix(line, "data:")) } } } func parseEvent(s string) (map[string]any, error) { var ev map[string]any if err := json.Unmarshal([]byte(s), &ev); err != nil { return nil, err } return ev, nil }