Proxify image enclosures
This commit is contained in:
parent
1a90c059e7
commit
fb2a73c91e
9 changed files with 56 additions and 30 deletions
|
@ -20,7 +20,7 @@ import (
|
||||||
|
|
||||||
// FindIcon try to find the website's icon.
|
// FindIcon try to find the website's icon.
|
||||||
func FindIcon(websiteURL string) (*model.Icon, error) {
|
func FindIcon(websiteURL string) (*model.Icon, error) {
|
||||||
rootURL := url.GetRootURL(websiteURL)
|
rootURL := url.RootURL(websiteURL)
|
||||||
client := http.NewClient(rootURL)
|
client := http.NewClient(rootURL)
|
||||||
response, err := client.Get()
|
response, err := client.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -72,9 +72,9 @@ func parseDocument(websiteURL string, data io.Reader) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if iconURL == "" {
|
if iconURL == "" {
|
||||||
iconURL = url.GetRootURL(websiteURL) + "favicon.ico"
|
iconURL = url.RootURL(websiteURL) + "favicon.ico"
|
||||||
} else {
|
} else {
|
||||||
iconURL, _ = url.GetAbsoluteURL(websiteURL, iconURL)
|
iconURL, _ = url.AbsoluteURL(websiteURL, iconURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
return iconURL, nil
|
return iconURL, nil
|
||||||
|
|
|
@ -88,7 +88,7 @@ func sanitizeAttributes(baseURL, tagName string, attributes []html.Attribute) ([
|
||||||
if tagName == "iframe" && !isValidIframeSource(attribute.Val) {
|
if tagName == "iframe" && !isValidIframeSource(attribute.Val) {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
value, err = url.GetAbsoluteURL(baseURL, value)
|
value, err = url.AbsoluteURL(baseURL, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ func parseDocument(websiteURL string, data io.Reader) (Subscriptions, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if feedURL, exists := s.Attr("href"); exists {
|
if feedURL, exists := s.Attr("href"); exists {
|
||||||
subscription.URL, _ = url.GetAbsoluteURL(websiteURL, feedURL)
|
subscription.URL, _ = url.AbsoluteURL(websiteURL, feedURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if subscription.Title == "" {
|
if subscription.Title == "" {
|
||||||
|
|
|
@ -8,8 +8,8 @@ import "net/url"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
// GetAbsoluteURL converts the input URL as absolute URL if necessary.
|
// AbsoluteURL converts the input URL as absolute URL if necessary.
|
||||||
func GetAbsoluteURL(baseURL, input string) (string, error) {
|
func AbsoluteURL(baseURL, input string) (string, error) {
|
||||||
if strings.HasPrefix(input, "//") {
|
if strings.HasPrefix(input, "//") {
|
||||||
input = "https://" + input[2:]
|
input = "https://" + input[2:]
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,13 @@ func GetAbsoluteURL(baseURL, input string) (string, error) {
|
||||||
return base.ResolveReference(u).String(), nil
|
return base.ResolveReference(u).String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootURL returns absolute URL without the path.
|
// RootURL returns absolute URL without the path.
|
||||||
func GetRootURL(websiteURL string) string {
|
func RootURL(websiteURL string) string {
|
||||||
if strings.HasPrefix(websiteURL, "//") {
|
if strings.HasPrefix(websiteURL, "//") {
|
||||||
websiteURL = "https://" + websiteURL[2:]
|
websiteURL = "https://" + websiteURL[2:]
|
||||||
}
|
}
|
||||||
|
|
||||||
absoluteURL, err := GetAbsoluteURL(websiteURL, "")
|
absoluteURL, err := AbsoluteURL(websiteURL, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return websiteURL
|
return websiteURL
|
||||||
}
|
}
|
||||||
|
@ -59,3 +59,13 @@ func IsHTTPS(websiteURL string) bool {
|
||||||
|
|
||||||
return strings.ToLower(parsedURL.Scheme) == "https"
|
return strings.ToLower(parsedURL.Scheme) == "https"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Domain returns only the domain part of the given URL.
|
||||||
|
func Domain(websiteURL string) string {
|
||||||
|
parsedURL, err := url.Parse(websiteURL)
|
||||||
|
if err != nil {
|
||||||
|
return websiteURL
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedURL.Host
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import "testing"
|
||||||
func TestGetAbsoluteURLWithAbsolutePath(t *testing.T) {
|
func TestGetAbsoluteURLWithAbsolutePath(t *testing.T) {
|
||||||
expected := `https://example.org/path/file.ext`
|
expected := `https://example.org/path/file.ext`
|
||||||
input := `/path/file.ext`
|
input := `/path/file.ext`
|
||||||
output, err := GetAbsoluteURL("https://example.org/folder/", input)
|
output, err := AbsoluteURL("https://example.org/folder/", input)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -19,7 +19,7 @@ func TestGetAbsoluteURLWithAbsolutePath(t *testing.T) {
|
||||||
func TestGetAbsoluteURLWithRelativePath(t *testing.T) {
|
func TestGetAbsoluteURLWithRelativePath(t *testing.T) {
|
||||||
expected := `https://example.org/folder/path/file.ext`
|
expected := `https://example.org/folder/path/file.ext`
|
||||||
input := `path/file.ext`
|
input := `path/file.ext`
|
||||||
output, err := GetAbsoluteURL("https://example.org/folder/", input)
|
output, err := AbsoluteURL("https://example.org/folder/", input)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -33,7 +33,7 @@ func TestGetAbsoluteURLWithRelativePath(t *testing.T) {
|
||||||
func TestGetAbsoluteURLWithRelativePaths(t *testing.T) {
|
func TestGetAbsoluteURLWithRelativePaths(t *testing.T) {
|
||||||
expected := `https://example.org/path/file.ext`
|
expected := `https://example.org/path/file.ext`
|
||||||
input := `path/file.ext`
|
input := `path/file.ext`
|
||||||
output, err := GetAbsoluteURL("https://example.org/folder", input)
|
output, err := AbsoluteURL("https://example.org/folder", input)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -47,7 +47,7 @@ func TestGetAbsoluteURLWithRelativePaths(t *testing.T) {
|
||||||
func TestWhenInputIsAlreadyAbsolute(t *testing.T) {
|
func TestWhenInputIsAlreadyAbsolute(t *testing.T) {
|
||||||
expected := `https://example.org/path/file.ext`
|
expected := `https://example.org/path/file.ext`
|
||||||
input := `https://example.org/path/file.ext`
|
input := `https://example.org/path/file.ext`
|
||||||
output, err := GetAbsoluteURL("https://example.org/folder/", input)
|
output, err := AbsoluteURL("https://example.org/folder/", input)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -61,7 +61,7 @@ func TestWhenInputIsAlreadyAbsolute(t *testing.T) {
|
||||||
func TestGetAbsoluteURLWithProtocolRelative(t *testing.T) {
|
func TestGetAbsoluteURLWithProtocolRelative(t *testing.T) {
|
||||||
expected := `https://static.example.org/path/file.ext`
|
expected := `https://static.example.org/path/file.ext`
|
||||||
input := `//static.example.org/path/file.ext`
|
input := `//static.example.org/path/file.ext`
|
||||||
output, err := GetAbsoluteURL("https://www.example.org/", input)
|
output, err := AbsoluteURL("https://www.example.org/", input)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -75,7 +75,7 @@ func TestGetAbsoluteURLWithProtocolRelative(t *testing.T) {
|
||||||
func TestGetRootURL(t *testing.T) {
|
func TestGetRootURL(t *testing.T) {
|
||||||
expected := `https://example.org/`
|
expected := `https://example.org/`
|
||||||
input := `https://example.org/path/file.ext`
|
input := `https://example.org/path/file.ext`
|
||||||
output := GetRootURL(input)
|
output := RootURL(input)
|
||||||
|
|
||||||
if expected != output {
|
if expected != output {
|
||||||
t.Errorf(`Unexpected output, got "%s" instead of "%s"`, output, expected)
|
t.Errorf(`Unexpected output, got "%s" instead of "%s"`, output, expected)
|
||||||
|
@ -85,7 +85,7 @@ func TestGetRootURL(t *testing.T) {
|
||||||
func TestGetRootURLWithProtocolRelativePath(t *testing.T) {
|
func TestGetRootURLWithProtocolRelativePath(t *testing.T) {
|
||||||
expected := `https://static.example.org/`
|
expected := `https://static.example.org/`
|
||||||
input := `//static.example.org/path/file.ext`
|
input := `//static.example.org/path/file.ext`
|
||||||
output := GetRootURL(input)
|
output := RootURL(input)
|
||||||
|
|
||||||
if expected != output {
|
if expected != output {
|
||||||
t.Errorf(`Unexpected output, got "%s" instead of "%s"`, output, expected)
|
t.Errorf(`Unexpected output, got "%s" instead of "%s"`, output, expected)
|
||||||
|
@ -105,3 +105,13 @@ func TestIsHTTPS(t *testing.T) {
|
||||||
t.Error("Unable to recognize malformed URL")
|
t.Error("Unable to recognize malformed URL")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetDomain(t *testing.T) {
|
||||||
|
expected := `static.example.org`
|
||||||
|
input := `http://static.example.org/`
|
||||||
|
output := Domain(input)
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Errorf(`Unexpected output, got "%s" instead of "%s"`, output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{ else if hasPrefix .MimeType "image/" }}
|
{{ else if hasPrefix .MimeType "image/" }}
|
||||||
<div class="enclosure-image">
|
<div class="enclosure-image">
|
||||||
<img src="{{ .URL }}" title="{{ .URL }} ({{ .MimeType }})" alt="{{ .URL }} ({{ .MimeType }})">
|
<img src="{{ proxyURL .URL }}" title="{{ .URL }} ({{ .MimeType }})" alt="{{ .URL }} ({{ .MimeType }})">
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,13 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/miniflux/miniflux2/config"
|
"github.com/miniflux/miniflux2/config"
|
||||||
"github.com/miniflux/miniflux2/errors"
|
"github.com/miniflux/miniflux2/errors"
|
||||||
"github.com/miniflux/miniflux2/locale"
|
"github.com/miniflux/miniflux2/locale"
|
||||||
|
"github.com/miniflux/miniflux2/reader/url"
|
||||||
"github.com/miniflux/miniflux2/server/route"
|
"github.com/miniflux/miniflux2/server/route"
|
||||||
"github.com/miniflux/miniflux2/server/template/helper"
|
"github.com/miniflux/miniflux2/server/template/helper"
|
||||||
"github.com/miniflux/miniflux2/server/ui/filter"
|
"github.com/miniflux/miniflux2/server/ui/filter"
|
||||||
|
@ -57,13 +57,15 @@ func (e *Engine) parseAll() {
|
||||||
"proxyFilter": func(data string) string {
|
"proxyFilter": func(data string) string {
|
||||||
return filter.ImageProxyFilter(e.router, data)
|
return filter.ImageProxyFilter(e.router, data)
|
||||||
},
|
},
|
||||||
"domain": func(websiteURL string) string {
|
"proxyURL": func(link string) string {
|
||||||
parsedURL, err := url.Parse(websiteURL)
|
if url.IsHTTPS(link) {
|
||||||
if err != nil {
|
return link
|
||||||
return websiteURL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedURL.Host
|
return filter.Proxify(e.router, link)
|
||||||
|
},
|
||||||
|
"domain": func(websiteURL string) string {
|
||||||
|
return url.Domain(websiteURL)
|
||||||
},
|
},
|
||||||
"isEmail": func(str string) bool {
|
"isEmail": func(str string) bool {
|
||||||
_, err := mail.ParseAddress(str)
|
_, err := mail.ParseAddress(str)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-27 21:07:53.218349526 -0800 PST m=+0.012535754
|
// 2017-12-01 22:19:52.660805124 -0800 PST m=+0.022084297
|
||||||
|
|
||||||
package template
|
package template
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ var templateViewsMap = map[string]string{
|
||||||
</div>
|
</div>
|
||||||
{{ else if hasPrefix .MimeType "image/" }}
|
{{ else if hasPrefix .MimeType "image/" }}
|
||||||
<div class="enclosure-image">
|
<div class="enclosure-image">
|
||||||
<img src="{{ .URL }}" title="{{ .URL }} ({{ .MimeType }})" alt="{{ .URL }} ({{ .MimeType }})">
|
<img src="{{ proxyURL .URL }}" title="{{ .URL }} ({{ .MimeType }})" alt="{{ .URL }} ({{ .MimeType }})">
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
@ -1054,7 +1054,7 @@ var templateViewsMapChecksums = map[string]string{
|
||||||
"edit_category": "cee720faadcec58289b707ad30af623d2ee66c1ce23a732965463250d7ff41c5",
|
"edit_category": "cee720faadcec58289b707ad30af623d2ee66c1ce23a732965463250d7ff41c5",
|
||||||
"edit_feed": "c5bc4c22bf7e8348d880395250545595d21fb8c8e723fc5d7cca68e25d250884",
|
"edit_feed": "c5bc4c22bf7e8348d880395250545595d21fb8c8e723fc5d7cca68e25d250884",
|
||||||
"edit_user": "c835d78f7cf36c11533db9cef253457a9003987d704070d59446cb2b0e84dcb9",
|
"edit_user": "c835d78f7cf36c11533db9cef253457a9003987d704070d59446cb2b0e84dcb9",
|
||||||
"entry": "2d7524cfd743f8a74fcf6bf7f4631fe4a61bb595173545d49793c845a450ff03",
|
"entry": "12e863c777368185091008adc851ddc0327317849f1566f7803be2b5bd358fd7",
|
||||||
"feed_entries": "9aff923b6c7452dec1514feada7e0d2bbc1ec21c6f5e9f48b2de41d1b731ffe4",
|
"feed_entries": "9aff923b6c7452dec1514feada7e0d2bbc1ec21c6f5e9f48b2de41d1b731ffe4",
|
||||||
"feeds": "c22af39b42ba9ca69ea0914ca789303ec2c5b484abcd4eaa49016e365381257c",
|
"feeds": "c22af39b42ba9ca69ea0914ca789303ec2c5b484abcd4eaa49016e365381257c",
|
||||||
"history": "947603cbde888516e62925f5d08fb0b13d930623d3ee4c690dbc22612fdda75e",
|
"history": "947603cbde888516e62925f5d08fb0b13d930623d3ee4c690dbc22612fdda75e",
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageProxyFilter rewrites image tag URLs without HTTPS to local proxy URL
|
// ImageProxyFilter rewrites image tag URLs without HTTPS to local proxy URL
|
||||||
func ImageProxyFilter(r *mux.Router, data string) string {
|
func ImageProxyFilter(router *mux.Router, data string) string {
|
||||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(data))
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data
|
return data
|
||||||
|
@ -25,8 +25,7 @@ func ImageProxyFilter(r *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 !url.IsHTTPS(srcAttr) {
|
||||||
path := route.Path(r, "proxy", "encodedURL", base64.StdEncoding.EncodeToString([]byte(srcAttr)))
|
img.SetAttr("src", Proxify(router, srcAttr))
|
||||||
img.SetAttr("src", path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -34,3 +33,8 @@ func ImageProxyFilter(r *mux.Router, data string) string {
|
||||||
output, _ := doc.Find("body").First().Html()
|
output, _ := doc.Find("body").First().Html()
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Proxify returns a proxified link.
|
||||||
|
func Proxify(router *mux.Router, link string) string {
|
||||||
|
return route.Path(router, "proxy", "encodedURL", base64.StdEncoding.EncodeToString([]byte(link)))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue