Преглед изворни кода

fix(urllib): fix rejection of valid proxy URLs in feeds

When attempting to set a proxy in a feed, due to a regression caused by 4cd9dd6af78044458f7a94ccf6e7fe181ff531d7
the form validation would now only accept HTTP(S) proxies, and reject SOCKS proxies, despite this being
a valid configuration before. Adding a new function to validate proxy URLs separates the concerns
and allows using a SOCKS proxy url again.
CULT PONY пре 5 дана
родитељ
комит
530b0c5739

+ 1 - 1
internal/ui/form/subscription.go

@@ -57,7 +57,7 @@ func (s *SubscriptionForm) Validate() *locale.LocalizedError {
 		return locale.NewLocalizedError("error.feed_invalid_urlrewrite_rule")
 	}
 
-	if s.ProxyURL != "" && !urllib.IsAbsoluteURL(s.ProxyURL) {
+	if s.ProxyURL != "" && !urllib.IsValidProxyURL(s.ProxyURL) {
 		return locale.NewLocalizedError("error.invalid_feed_proxy_url")
 	}
 

+ 17 - 0
internal/urllib/url.go

@@ -43,6 +43,11 @@ func hasHTTPPrefix(inputURL string) bool {
 	return strings.HasPrefix(inputURL, "https://") || strings.HasPrefix(inputURL, "http://")
 }
 
+// hasSOCKSPrefix reports whether the URL string begins with an SOCKS5 or SOCKS5H scheme.
+func hasSOCKSPrefix(inputURL string) bool {
+	return strings.HasPrefix(inputURL, "socks5://") || strings.HasPrefix(inputURL, "socks5h://")
+}
+
 // IsAbsoluteURL reports whether the link is absolute and starts with an HTTP or HTTPS scheme.
 func IsAbsoluteURL(inputURL string) bool {
 	if !hasHTTPPrefix(inputURL) {
@@ -55,6 +60,18 @@ func IsAbsoluteURL(inputURL string) bool {
 	return parsedURL.IsAbs()
 }
 
+// IsValidProxyURL reports whether the url is absolute, has a host and starts with an HTTP, HTTPS, SOCKS5 or SOCKS5H scheme.
+func IsValidProxyURL(inputURL string) bool {
+	if !hasHTTPPrefix(inputURL) && !hasSOCKSPrefix(inputURL) {
+		return false
+	}
+	parsedURL, err := url.Parse(inputURL)
+	if err != nil {
+		return false
+	}
+	return parsedURL.IsAbs() && parsedURL.Host != ""
+}
+
 // resolveToAbsoluteURL resolves a relative URL using a base URL, parsing the base only if needed.
 func resolveToAbsoluteURL(parsedBaseURL *url.URL, baseURL, relativeURL string) (string, error) {
 	// Avoid parsing the relative URL if it's already absolute

+ 28 - 0
internal/urllib/url_test.go

@@ -68,6 +68,34 @@ func TestIsAbsoluteURL(t *testing.T) {
 	}
 }
 
+func TestIsValidProxyURL(t *testing.T) {
+	scenarios := map[string]bool{
+		"http://127.0.0.1:3128":      true,
+		"http://[::1]:1055":          true,
+		"https://proxy.example.org":  true,
+		"socks5://127.0.0.1:1080":    true,
+		"socks5h://127.0.0.1:1080":   true,
+		"socks5://[::1]:1055":        true,
+		"socks5h://[::1]:1055":       true,
+		"socks5://[::1%25eno1]:1055": true,
+		"ftp://host":                 false,
+		"/relative/path":             false,
+		"invalid url":                false,
+		"http://[::1":                false,
+		"http:///var/run/socket":     false,
+		"sock:///socket.file":        false,
+		"socks5://[::1%eno1]:1055":   false,
+		"":                           false,
+	}
+
+	for input, expected := range scenarios {
+		actual := IsValidProxyURL(input)
+		if actual != expected {
+			t.Errorf(`Unexpected result, got %v instead of %v for %q`, actual, expected, input)
+		}
+	}
+}
+
 func TestAbsoluteURL(t *testing.T) {
 	type absoluteScenario struct {
 		name          string

+ 2 - 2
internal/validator/feed.go

@@ -48,7 +48,7 @@ func ValidateFeedCreation(store *storage.Storage, userID int64, request *model.F
 		}
 	}
 
-	if request.ProxyURL != "" && !urllib.IsAbsoluteURL(request.ProxyURL) {
+	if request.ProxyURL != "" && !urllib.IsValidProxyURL(request.ProxyURL) {
 		return locale.NewLocalizedError("error.invalid_feed_proxy_url")
 	}
 
@@ -122,7 +122,7 @@ func ValidateFeedModification(store *storage.Storage, userID, feedID int64, requ
 			return locale.NewLocalizedError("error.proxy_url_not_empty")
 		}
 
-		if !urllib.IsAbsoluteURL(*request.ProxyURL) {
+		if !urllib.IsValidProxyURL(*request.ProxyURL) {
 			return locale.NewLocalizedError("error.invalid_feed_proxy_url")
 		}
 	}

+ 1 - 1
internal/validator/subscription.go

@@ -15,7 +15,7 @@ func ValidateSubscriptionDiscovery(request *model.SubscriptionDiscoveryRequest)
 		return locale.NewLocalizedError("error.invalid_site_url")
 	}
 
-	if request.ProxyURL != "" && !urllib.IsAbsoluteURL(request.ProxyURL) {
+	if request.ProxyURL != "" && !urllib.IsValidProxyURL(request.ProxyURL) {
 		return locale.NewLocalizedError("error.invalid_proxy_url")
 	}