Make image proxy configurable
Adds IMAGE_PROXY configuration setting to change image proxy filter behaviour: - none = No proxy - http-only = Proxy only non-HTTPS images (default) - all = Proxy everything
This commit is contained in:
parent
6fd6f79daf
commit
c926498d3d
4 changed files with 138 additions and 11 deletions
|
@ -26,6 +26,7 @@ const (
|
||||||
defaultCertDomain = ""
|
defaultCertDomain = ""
|
||||||
defaultCertCache = "/tmp/cert_cache"
|
defaultCertCache = "/tmp/cert_cache"
|
||||||
defaultCleanupFrequency = 24
|
defaultCleanupFrequency = 24
|
||||||
|
defaultProxyImages = "http-only"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config manages configuration parameters.
|
// Config manages configuration parameters.
|
||||||
|
@ -217,6 +218,11 @@ func (c *Config) PocketConsumerKey(defaultValue string) string {
|
||||||
return c.get("POCKET_CONSUMER_KEY", defaultValue)
|
return c.get("POCKET_CONSUMER_KEY", defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyImages returns "none" to never proxy, "http-only" to proxy non-HTTPS, "all" to always proxy.
|
||||||
|
func (c *Config) ProxyImages() string {
|
||||||
|
return c.get("PROXY_IMAGES", defaultProxyImages)
|
||||||
|
}
|
||||||
|
|
||||||
// NewConfig returns a new Config.
|
// NewConfig returns a new Config.
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
cfg := &Config{
|
cfg := &Config{
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/miniflux/miniflux/config"
|
||||||
"github.com/miniflux/miniflux/http/route"
|
"github.com/miniflux/miniflux/http/route"
|
||||||
"github.com/miniflux/miniflux/url"
|
"github.com/miniflux/miniflux/url"
|
||||||
|
|
||||||
|
@ -15,8 +16,13 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageProxyFilter rewrites image tag URLs without HTTPS to local proxy URL
|
// ImageProxyFilter rewrites image tag URLs to local proxy URL (by default only non-HTTPS URLs)
|
||||||
func ImageProxyFilter(router *mux.Router, data string) string {
|
func ImageProxyFilter(router *mux.Router, cfg *config.Config, data string) string {
|
||||||
|
proxyImages := cfg.ProxyImages()
|
||||||
|
if proxyImages == "none" {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(data))
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data
|
return data
|
||||||
|
@ -24,7 +30,7 @@ func ImageProxyFilter(router *mux.Router, data string) string {
|
||||||
|
|
||||||
doc.Find("img").Each(func(i int, img *goquery.Selection) {
|
doc.Find("img").Each(func(i int, img *goquery.Selection) {
|
||||||
if srcAttr, ok := img.Attr("src"); ok {
|
if srcAttr, ok := img.Attr("src"); ok {
|
||||||
if !url.IsHTTPS(srcAttr) {
|
if proxyImages == "all" || !url.IsHTTPS(srcAttr) {
|
||||||
img.SetAttr("src", Proxify(router, srcAttr))
|
img.SetAttr("src", Proxify(router, srcAttr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,24 @@ package filter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/miniflux/miniflux/config"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProxyFilterWithHttp(t *testing.T) {
|
func TestProxyFilterWithHttpDefault(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "http-only")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
|
input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
|
||||||
output := ImageProxyFilter(r, input)
|
output := ImageProxyFilter(r, c, input)
|
||||||
expected := `<p><img src="/proxy/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
|
expected := `<p><img src="/proxy/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
|
||||||
|
|
||||||
if expected != output {
|
if expected != output {
|
||||||
|
@ -24,12 +31,118 @@ func TestProxyFilterWithHttp(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProxyFilterWithHttps(t *testing.T) {
|
func TestProxyFilterWithHttpsDefault(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "http-only")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
||||||
output := ImageProxyFilter(r, input)
|
output := ImageProxyFilter(r, c, input)
|
||||||
|
expected := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Errorf(`Not expected output: got "%s" instead of "%s"`, output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxyFilterWithHttpNever(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "none")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
|
input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
output := ImageProxyFilter(r, c, input)
|
||||||
|
expected := input
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Errorf(`Not expected output: got "%s" instead of "%s"`, output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxyFilterWithHttpsNever(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "none")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
|
input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
output := ImageProxyFilter(r, c, input)
|
||||||
|
expected := input
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Errorf(`Not expected output: got "%s" instead of "%s"`, output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxyFilterWithHttpAlways(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "all")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
|
input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
output := ImageProxyFilter(r, c, input)
|
||||||
|
expected := `<p><img src="/proxy/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Errorf(`Not expected output: got "%s" instead of "%s"`, output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxyFilterWithHttpsAlways(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "all")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
|
input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
output := ImageProxyFilter(r, c, input)
|
||||||
|
expected := `<p><img src="/proxy/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Errorf(`Not expected output: got "%s" instead of "%s"`, output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxyFilterWithHttpInvalid(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "invalid")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
|
input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
output := ImageProxyFilter(r, c, input)
|
||||||
|
expected := `<p><img src="/proxy/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Errorf(`Not expected output: got "%s" instead of "%s"`, output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxyFilterWithHttpsInvalid(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("PROXY_IMAGES", "invalid")
|
||||||
|
c := config.NewConfig()
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/proxy/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
|
||||||
|
|
||||||
|
input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
output := ImageProxyFilter(r, c, input)
|
||||||
expected := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
expected := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
|
||||||
|
|
||||||
if expected != output {
|
if expected != output {
|
||||||
|
|
|
@ -46,14 +46,16 @@ func (f *funcMap) Map() template.FuncMap {
|
||||||
return template.HTML(str)
|
return template.HTML(str)
|
||||||
},
|
},
|
||||||
"proxyFilter": func(data string) string {
|
"proxyFilter": func(data string) string {
|
||||||
return filter.ImageProxyFilter(f.router, data)
|
return filter.ImageProxyFilter(f.router, f.cfg, data)
|
||||||
},
|
},
|
||||||
"proxyURL": func(link string) string {
|
"proxyURL": func(link string) string {
|
||||||
if url.IsHTTPS(link) {
|
proxyImages := f.cfg.ProxyImages()
|
||||||
return link
|
|
||||||
|
if proxyImages == "all" || (proxyImages != "none" && !url.IsHTTPS(link)) {
|
||||||
|
return filter.Proxify(f.router, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
return filter.Proxify(f.router, link)
|
return link
|
||||||
},
|
},
|
||||||
"domain": func(websiteURL string) string {
|
"domain": func(websiteURL string) string {
|
||||||
return url.Domain(websiteURL)
|
return url.Domain(websiteURL)
|
||||||
|
|
Loading…
Reference in a new issue