From fd5808d0250cd17ec420225a010ec273971a471b Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Thu, 26 Oct 2023 17:01:47 -0500 Subject: [PATCH] Implement flushing copy on proxy response (#416) --- http/proxy_server.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/http/proxy_server.go b/http/proxy_server.go index c62addc..c3f9c22 100644 --- a/http/proxy_server.go +++ b/http/proxy_server.go @@ -324,12 +324,34 @@ func (s *ProxyServer) proxyToTarget(w http.ResponseWriter, r *http.Request, pass // Set response code and copy the body. w.WriteHeader(resp.StatusCode) - if _, err := io.Copy(w, resp.Body); err != nil { + if err := copyAndFlush(w, resp.Body); err != nil { log.Printf("http: proxy response error: %s", err) return } } +// copyAndFlush implements a basic io.Copy() but calls dst.Flush() after every write. +// dst must implement http.Flusher or else it will panic. +func copyAndFlush(dst io.Writer, src io.Reader) error { + buf := make([]byte, 32*1024) + + for { + n, err := src.Read(buf) + if n > 0 { + if _, e := dst.Write(buf[:n]); e != nil { + return err + } + dst.(http.Flusher).Flush() + } + + if err == io.EOF { + return nil + } else if err != nil { + return err + } + } +} + func (s *ProxyServer) isWriteRequest(r *http.Request) bool { return r.Method != http.MethodGet && r.Method != http.MethodHead }