Просмотр исходного кода

fix: use BASE_URL instead of `r.Host` to generate absolute media proxy URL

Frédéric Guillot 1 год назад
Родитель
Сommit
d048d59d39

+ 3 - 3
internal/api/entry.go

@@ -36,14 +36,14 @@ func (h *handler) getEntryFromBuilder(w http.ResponseWriter, r *http.Request, b
 		return
 	}
 
-	entry.Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entry.Content)
+	entry.Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, entry.Content)
 	proxyOption := config.Opts.MediaProxyMode()
 
 	for i := range entry.Enclosures {
 		if proxyOption == "all" || proxyOption != "none" && !urllib.IsHTTPS(entry.Enclosures[i].URL) {
 			for _, mediaType := range config.Opts.MediaProxyResourceTypes() {
 				if strings.HasPrefix(entry.Enclosures[i].MimeType, mediaType+"/") {
-					entry.Enclosures[i].URL = mediaproxy.ProxifyAbsoluteURL(h.router, r.Host, entry.Enclosures[i].URL)
+					entry.Enclosures[i].URL = mediaproxy.ProxifyAbsoluteURL(h.router, entry.Enclosures[i].URL)
 					break
 				}
 			}
@@ -164,7 +164,7 @@ func (h *handler) findEntries(w http.ResponseWriter, r *http.Request, feedID int
 	}
 
 	for i := range entries {
-		entries[i].Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entries[i].Content)
+		entries[i].Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, entries[i].Content)
 	}
 
 	json.OK(w, r, &entriesResponse{Total: count, Entries: entries})

+ 23 - 0
internal/config/config_test.go

@@ -259,6 +259,29 @@ func TestCustomBaseURLWithTrailingSlash(t *testing.T) {
 	}
 }
 
+func TestCustomBaseURLWithCustomPort(t *testing.T) {
+	os.Clearenv()
+	os.Setenv("BASE_URL", "http://example.org:88/folder/")
+
+	parser := NewParser()
+	opts, err := parser.ParseEnvironmentVariables()
+	if err != nil {
+		t.Fatalf(`Parsing failure: %v`, err)
+	}
+
+	if opts.BaseURL() != "http://example.org:88/folder" {
+		t.Fatalf(`Unexpected base URL, got "%s"`, opts.BaseURL())
+	}
+
+	if opts.RootURL() != "http://example.org:88" {
+		t.Fatalf(`Unexpected root URL, got "%s"`, opts.RootURL())
+	}
+
+	if opts.BasePath() != "/folder" {
+		t.Fatalf(`Unexpected base path, got "%s"`, opts.BasePath())
+	}
+}
+
 func TestBaseURLWithoutScheme(t *testing.T) {
 	os.Clearenv()
 	os.Setenv("BASE_URL", "example.org/folder/")

+ 1 - 1
internal/fever/handler.go

@@ -324,7 +324,7 @@ func (h *handler) handleItems(w http.ResponseWriter, r *http.Request) {
 			FeedID:    entry.FeedID,
 			Title:     entry.Title,
 			Author:    entry.Author,
-			HTML:      mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entry.Content),
+			HTML:      mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, entry.Content),
 			URL:       entry.URL,
 			IsSaved:   isSaved,
 			IsRead:    isRead,

+ 2 - 2
internal/googlereader/handler.go

@@ -1003,14 +1003,14 @@ func (h *handler) streamItemContentsHandler(w http.ResponseWriter, r *http.Reque
 			categories = append(categories, userStarred)
 		}
 
-		entry.Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, r.Host, entry.Content)
+		entry.Content = mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, entry.Content)
 		proxyOption := config.Opts.MediaProxyMode()
 
 		for i := range entry.Enclosures {
 			if proxyOption == "all" || proxyOption != "none" && !urllib.IsHTTPS(entry.Enclosures[i].URL) {
 				for _, mediaType := range config.Opts.MediaProxyResourceTypes() {
 					if strings.HasPrefix(entry.Enclosures[i].MimeType, mediaType+"/") {
-						entry.Enclosures[i].URL = mediaproxy.ProxifyAbsoluteURL(h.router, r.Host, entry.Enclosures[i].URL)
+						entry.Enclosures[i].URL = mediaproxy.ProxifyAbsoluteURL(h.router, entry.Enclosures[i].URL)
 						break
 					}
 				}

+ 13 - 11
internal/mediaproxy/media_proxy_test.go

@@ -174,7 +174,7 @@ func TestAbsoluteProxyFilterWithHttpsAlways(t *testing.T) {
 	r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
 
 	input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
-	output := RewriteDocumentWithAbsoluteProxyURL(r, "localhost", input)
+	output := RewriteDocumentWithAbsoluteProxyURL(r, input)
 	expected := `<p><img src="http://localhost/proxy/LdPNR1GBDigeeNp2ArUQRyZsVqT_PWLfHGjYFrrWWIY=/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
 
 	if expected != output {
@@ -182,12 +182,10 @@ func TestAbsoluteProxyFilterWithHttpsAlways(t *testing.T) {
 	}
 }
 
-func TestAbsoluteProxyFilterWithHttpsScheme(t *testing.T) {
+func TestAbsoluteProxyFilterWithCustomPortInBaseURL(t *testing.T) {
 	os.Clearenv()
-	os.Setenv("PROXY_OPTION", "all")
-	os.Setenv("PROXY_MEDIA_TYPES", "image")
-	os.Setenv("PROXY_PRIVATE_KEY", "test")
-	os.Setenv("HTTPS", "1")
+	os.Setenv("BASE_URL", "http://example.org:88/folder/")
+	os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
 
 	var err error
 	parser := config.NewParser()
@@ -196,12 +194,16 @@ func TestAbsoluteProxyFilterWithHttpsScheme(t *testing.T) {
 		t.Fatalf(`Parsing failure: %v`, err)
 	}
 
+	if config.Opts.BaseURL() != "http://example.org:88/folder" {
+		t.Fatalf(`Unexpected base URL, got "%s"`, config.Opts.BaseURL())
+	}
+
 	r := mux.NewRouter()
 	r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
 
-	input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
-	output := RewriteDocumentWithAbsoluteProxyURL(r, "localhost", input)
-	expected := `<p><img src="https://localhost/proxy/LdPNR1GBDigeeNp2ArUQRyZsVqT_PWLfHGjYFrrWWIY=/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
+	input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
+	output := RewriteDocumentWithAbsoluteProxyURL(r, input)
+	expected := `<p><img src="http://example.org:88/folder/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
 
 	if expected != output {
 		t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
@@ -225,7 +227,7 @@ func TestAbsoluteProxyFilterWithHttpsAlwaysAndAudioTag(t *testing.T) {
 	r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
 
 	input := `<audio src="https://website/folder/audio.mp3"></audio>`
-	output := RewriteDocumentWithAbsoluteProxyURL(r, "localhost", input)
+	output := RewriteDocumentWithAbsoluteProxyURL(r, input)
 	expected := `<audio src="http://localhost/proxy/EmBTvmU5B17wGuONkeknkptYopW_Tl6Y6_W8oYbN_Xs=/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9hdWRpby5tcDM="></audio>`
 
 	if expected != output {
@@ -300,7 +302,7 @@ func TestAbsoluteProxyFilterWithHttpsAlwaysAndCustomProxyServer(t *testing.T) {
 	r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
 
 	input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
-	output := RewriteDocumentWithAbsoluteProxyURL(r, "localhost", input)
+	output := RewriteDocumentWithAbsoluteProxyURL(r, input)
 	expected := `<p><img src="https://proxy-example/proxy/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
 
 	if expected != output {

+ 2 - 5
internal/mediaproxy/rewriter.go

@@ -21,11 +21,8 @@ func RewriteDocumentWithRelativeProxyURL(router *mux.Router, htmlDocument string
 	return genericProxyRewriter(router, ProxifyRelativeURL, htmlDocument)
 }
 
-func RewriteDocumentWithAbsoluteProxyURL(router *mux.Router, host, htmlDocument string) string {
-	proxifyFunction := func(router *mux.Router, url string) string {
-		return ProxifyAbsoluteURL(router, host, url)
-	}
-	return genericProxyRewriter(router, proxifyFunction, htmlDocument)
+func RewriteDocumentWithAbsoluteProxyURL(router *mux.Router, htmlDocument string) string {
+	return genericProxyRewriter(router, ProxifyAbsoluteURL, htmlDocument)
 }
 
 func genericProxyRewriter(router *mux.Router, proxifyFunction urlProxyRewriter, htmlDocument string) string {

+ 9 - 11
internal/mediaproxy/url.go

@@ -9,13 +9,11 @@ import (
 	"encoding/base64"
 	"log/slog"
 	"net/url"
-	"path"
-
-	"miniflux.app/v2/internal/http/route"
 
 	"github.com/gorilla/mux"
 
 	"miniflux.app/v2/internal/config"
+	"miniflux.app/v2/internal/http/route"
 )
 
 func ProxifyRelativeURL(router *mux.Router, mediaURL string) string {
@@ -33,7 +31,7 @@ func ProxifyRelativeURL(router *mux.Router, mediaURL string) string {
 	return route.Path(router, "proxy", "encodedDigest", base64.URLEncoding.EncodeToString(digest), "encodedURL", base64.URLEncoding.EncodeToString([]byte(mediaURL)))
 }
 
-func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string) string {
+func ProxifyAbsoluteURL(router *mux.Router, mediaURL string) string {
 	if mediaURL == "" {
 		return ""
 	}
@@ -43,12 +41,13 @@ func ProxifyAbsoluteURL(router *mux.Router, host, mediaURL string) string {
 	}
 
 	proxifiedUrl := ProxifyRelativeURL(router, mediaURL)
-	scheme := "http"
-	if config.Opts.HTTPS {
-		scheme = "https"
+
+	absoluteURL, err := url.JoinPath(config.Opts.BaseURL(), proxifiedUrl)
+	if err != nil {
+		return mediaURL
 	}
 
-	return scheme + "://" + host + proxifiedUrl
+	return absoluteURL
 }
 
 func proxifyURLWithCustomProxy(mediaURL, customProxyURL string) string {
@@ -56,7 +55,7 @@ func proxifyURLWithCustomProxy(mediaURL, customProxyURL string) string {
 		return mediaURL
 	}
 
-	proxyUrl, err := url.Parse(customProxyURL)
+	absoluteURL, err := url.JoinPath(customProxyURL, base64.URLEncoding.EncodeToString([]byte(mediaURL)))
 	if err != nil {
 		slog.Error("Incorrect custom media proxy URL",
 			slog.String("custom_proxy_url", customProxyURL),
@@ -65,6 +64,5 @@ func proxifyURLWithCustomProxy(mediaURL, customProxyURL string) string {
 		return mediaURL
 	}
 
-	proxyUrl.Path = path.Join(proxyUrl.Path, base64.URLEncoding.EncodeToString([]byte(mediaURL)))
-	return proxyUrl.String()
+	return absoluteURL
 }