aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Peter De Wachter <pdewacht@gmail.com>2019-08-14 17:54:02 +0200
committerGravatar Frédéric Guillot <fred@miniflux.net>2019-09-10 20:43:44 -0700
commit937492f6f554d51d8cae62829b6229071cac994e (patch)
tree8b1d4a1c142933a7d79ad8c454e99f58bf17fffb
parentb94160df725a52af53f113bf27de7a7b8723174c (diff)
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.
-rw-r--r--http/response/builder.go5
-rw-r--r--ui/proxy.go29
2 files changed, 25 insertions, 9 deletions
diff --git a/http/response/builder.go b/http/response/builder.go
index f17c62e..b8ba1ef 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 e9f8ec0..1a847fa 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()
})