Чтение и потоковая передача ответов от http-серверов, использующих транспорт фрагментов

У меня есть http-сервер, который отвечает на запросы через протокол чанков. В этом простом примере он отвечает временем каждую секунду. У меня есть другой сервер, который перенаправляет запросы на этот сервер времени и отвечает тем же протоколом фрагментов.

curl -i localhost:8000 возвращает правильное значение

однако curl -i localhost:9000 возвращает фрагментированный ответ, но только через три секунды (не каждую секунду). Это означает, что каким-то образом io.copy действительно не сбрасывает вывод, как только он приходит.


person Keeto    schedule 31.08.2016    source источник


Ответы (1)


io.Copy должен скопировать все содержимое перед вызовом Flush. Если вы хотите, чтобы содержимое было отправлено до того, как буфер заполнится, вам нужно вызывать flush после каждой записи самостоятельно.

Полная версия io.Copy, которая сбрасывает http.ResponseWriter после каждой записи, будет выглядеть так:

func flushCopy(dst io.Writer, src io.Reader) (written int64, err error) {
    buf := make([]byte, 1024 * 8)
    flusher, canFlush := dst.(http.Flusher)
    for {
        nr, er := src.Read(buf)
        if nr > 0 {
            nw, ew := dst.Write(buf[0:nr])
            if nw > 0 {
                if canFlush {
                    flusher.Flush()
                }
                written += int64(nw)
            }
            if ew != nil {
                err = ew
                break
            }
            if nr != nw {
                err = io.ErrShortWrite
                break
            }
        }
        if er == io.EOF {
            break
        }
        if er != nil {
            err = er
            break
        }
    }
    return written, err
}
person JimB    schedule 01.09.2016