From 937492f6f554d51d8cae62829b6229071cac994e Mon Sep 17 00:00:00 2001 From: Peter De Wachter Date: Wed, 14 Aug 2019 17:54:02 +0200 Subject: [PATCH] Do not buffer responses in the image proxy The image proxy buffered the whole image before sending it to the browser. If the image is large and/or hosted on a slow server, this caused a long delay before the user's browser could display anything. --- http/response/builder.go | 5 +++++ ui/proxy.go | 29 ++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/http/response/builder.go b/http/response/builder.go index f17c62e4..b8ba1efa 100644 --- a/http/response/builder.go +++ b/http/response/builder.go @@ -8,6 +8,7 @@ import ( "compress/flate" "compress/gzip" "fmt" + "io" "net/http" "strings" "time" @@ -84,6 +85,10 @@ func (b *Builder) Write() { b.compress([]byte(v)) case error: b.compress([]byte(v.Error())) + case io.Reader: + // Compression not implemented in this case + b.writeHeaders() + io.Copy(b.w, v) } } diff --git a/ui/proxy.go b/ui/proxy.go index e9f8ec08..1a847fa9 100644 --- a/ui/proxy.go +++ b/ui/proxy.go @@ -7,10 +7,10 @@ package ui // import "miniflux.app/ui" import ( "encoding/base64" "errors" - "io/ioutil" "net/http" "time" + "miniflux.app/config" "miniflux.app/crypto" "miniflux.app/http/client" "miniflux.app/http/request" @@ -37,24 +37,35 @@ func (h *handler) imageProxy(w http.ResponseWriter, r *http.Request) { return } - clt := client.New(string(decodedURL)) - resp, err := clt.Get() + req, err := http.NewRequest("GET", string(decodedURL), nil) if err != nil { html.ServerError(w, r, err) return } + req.Header.Add("User-Agent", client.DefaultUserAgent) + req.Header.Add("Connection", "close") - if resp.HasServerFailure() { + clt := &http.Client{ + Timeout: time.Duration(config.Opts.HTTPClientTimeout()) * time.Second, + } + + resp, err := clt.Do(req) + if err != nil { + html.ServerError(w, r, err) + return + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { html.NotFound(w, r) return } - body, _ := ioutil.ReadAll(resp.Body) - etag := crypto.HashFromBytes(body) + etag := crypto.HashFromBytes(decodedURL) - response.New(w ,r).WithCaching(etag, 72*time.Hour, func(b *response.Builder) { - b.WithHeader("Content-Type", resp.ContentType) - b.WithBody(body) + response.New(w, r).WithCaching(etag, 72*time.Hour, func(b *response.Builder) { + b.WithHeader("Content-Type", resp.Header.Get("Content-Type")) + b.WithBody(resp.Body) b.WithoutCompression() b.Write() })