2
votes

I need to read sse in my golang app, but instead of real-time, events return buffered. As I can see, this is because of standard golang transport. How can I fix this, without implementing my own transport? This code is inspired by cryptix solution:

resp, _ := http.Get(sseURL)
events := make(chan Event)
wg:= sync.WaitGroup{}
wg.Add(1)
go func() {
    event:= Event{}
    reader := bufio.NewReader(resp.Body)

    for {
        line, err := reader.ReadBytes('\n')

        if err != nil {
            log.Println(os.Stderr, "error during resp.Body read:%s\n", err)
            close(events)
        }

        json.Unmarshal(line,&event)

        events<-event
    }
    wg.Done()
}()

go func(){
    for ev:= range events {
        log.Println(ev)
    }
}()
wg.Wait()
1
There shouldn't be a delay because of the client's transport. Have you verified the timing by watching the data on the wire? (also, if you have newline delimited json, you can use json.Decoder directly)JimB
Thx, @JimB. Yes, I verified that data is sent real time with curl.hjortron
This method works correctly, provided the server flushed a complete json object and newline. (I'm seeing less then 1µs delay). You do need to fix problems like sending on a closed channel, and Println where you wanted Fprintf, but that shouldn't add any delay. Make sure the server is sending exactly the data you expect, when you expect it to.JimB

1 Answers

1
votes

I figured out, data was buffered by nginx, because of transparent compression. So, to get data without delay we must disable compression like this:

client := &http.Client{}
transport := &http.Transport{}
transport.DisableCompression = true
client.Transport = transport
req, err := http.NewRequest("GET", essURL, nil)
if err != nil {
    log.Fatal(err);
}
resp, _ := client.Do(req)

reader := bufio.NewReader(resp.Body)
for {
    line,_:=reader.ReadSlice('\n')
    log.Println(string(line))       
}