package client import ( "bufio" "encoding/json" "io" "strings" ) // sseDecoder reads the subset of the Server-Sent Events format the server // emits: "event:" and "data:" lines, one JSON payload per event. type sseDecoder struct { sc *bufio.Scanner } func newSSEDecoder(r io.Reader) *sseDecoder { sc := bufio.NewScanner(r) sc.Buffer(make([]byte, 0, 8<<10), 1<<20) return &sseDecoder{sc: sc} } // next returns the next event, or nil for a comment or keepalive line. func (d *sseDecoder) next() (*Event, error) { var ( name string data string ) for d.sc.Scan() { line := d.sc.Text() switch { case line == "": if data == "" { name = "" continue } var ev Event if err := json.Unmarshal([]byte(data), &ev); err != nil { return nil, nil // skip a payload we cannot read } if ev.Type == "" { ev.Type = name } return &ev, nil case strings.HasPrefix(line, ":"): continue case strings.HasPrefix(line, "event:"): name = strings.TrimSpace(strings.TrimPrefix(line, "event:")) case strings.HasPrefix(line, "data:"): data += strings.TrimSpace(strings.TrimPrefix(line, "data:")) } } if err := d.sc.Err(); err != nil { return nil, err } return nil, io.EOF }