Normalize server URLs before connecting (#861)
* Fix #304: normalize server URLs before connecting Prepend http:// when no scheme is present and strip trailing slashes for all server types. For Jellyfin, additionally strip /web/index.html and /web path suffixes that users copy from the browser URL bar. Normalization is applied in ServerManager.connect() on the by-value parameter, so stored config is never mutated. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * move url normalize funcs --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e21908cd24
commit
9dd606ce73
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dweymouth/go-jellyfin"
|
"github.com/dweymouth/go-jellyfin"
|
||||||
@@ -179,6 +180,14 @@ func (s *ServerManager) connect(connection ServerConnection, password string) (m
|
|||||||
var cli, altCli mediaprovider.Server
|
var cli, altCli mediaprovider.Server
|
||||||
timeout := time.Second * time.Duration(s.config.Application.RequestTimeoutSeconds)
|
timeout := time.Second * time.Duration(s.config.Application.RequestTimeoutSeconds)
|
||||||
|
|
||||||
|
if connection.ServerType == ServerTypeJellyfin {
|
||||||
|
connection.Hostname = NormalizeJellyfinURL(connection.Hostname)
|
||||||
|
connection.AltHostname = NormalizeJellyfinURL(connection.AltHostname)
|
||||||
|
} else {
|
||||||
|
connection.Hostname = NormalizeServerURL(connection.Hostname)
|
||||||
|
connection.AltHostname = NormalizeServerURL(connection.AltHostname)
|
||||||
|
}
|
||||||
|
|
||||||
if connection.ServerType == ServerTypeJellyfin {
|
if connection.ServerType == ServerTypeJellyfin {
|
||||||
client, err := jellyfin.NewClient(connection.Hostname, res.AppName, res.AppVersion, jellyfin.WithTimeout(timeout))
|
client, err := jellyfin.NewClient(connection.Hostname, res.AppName, res.AppVersion, jellyfin.WithTimeout(timeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -266,3 +275,28 @@ func (s *ServerManager) checkSetInsecureSkipVerify(skip bool, cli *http.Client)
|
|||||||
func (a *ServerManager) GetServer() mediaprovider.MediaProvider {
|
func (a *ServerManager) GetServer() mediaprovider.MediaProvider {
|
||||||
return a.Server
|
return a.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NormalizeServerURL applies common normalization to a server URL:
|
||||||
|
// prepends "http://" if no scheme is present, then strips trailing slashes.
|
||||||
|
func NormalizeServerURL(rawURL string) string {
|
||||||
|
if rawURL == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if !strings.Contains(rawURL, "://") {
|
||||||
|
rawURL = "http://" + rawURL
|
||||||
|
}
|
||||||
|
rawURL = strings.TrimRight(rawURL, "/")
|
||||||
|
return rawURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizeJellyfinURL applies common normalization then additionally strips
|
||||||
|
// known Jellyfin web UI path suffixes (/web/index.html and /web).
|
||||||
|
func NormalizeJellyfinURL(rawURL string) string {
|
||||||
|
rawURL = NormalizeServerURL(rawURL)
|
||||||
|
if strings.HasSuffix(rawURL, "/web/index.html") {
|
||||||
|
rawURL = strings.TrimSuffix(rawURL, "/web/index.html")
|
||||||
|
} else if strings.HasSuffix(rawURL, "/web") {
|
||||||
|
rawURL = strings.TrimSuffix(rawURL, "/web")
|
||||||
|
}
|
||||||
|
return rawURL
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package backend
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestNormalizeServerURL(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"", ""},
|
||||||
|
{"http://192.168.1.1:8096", "http://192.168.1.1:8096"},
|
||||||
|
{"https://music.example.com", "https://music.example.com"},
|
||||||
|
{"192.168.1.1:4533", "http://192.168.1.1:4533"},
|
||||||
|
{"music.example.com", "http://music.example.com"},
|
||||||
|
{"http://192.168.1.1:8096/", "http://192.168.1.1:8096"},
|
||||||
|
{"http://192.168.1.1:8096///", "http://192.168.1.1:8096"},
|
||||||
|
{"192.168.1.1:8096/", "http://192.168.1.1:8096"},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
got := NormalizeServerURL(tt.input)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("NormalizeServerURL(%q) = %q, want %q", tt.input, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNormalizeJellyfinURL(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"", ""},
|
||||||
|
{"http://192.168.1.1:8096", "http://192.168.1.1:8096"},
|
||||||
|
{"192.168.1.1:8096", "http://192.168.1.1:8096"},
|
||||||
|
{"192.168.1.1:8096/", "http://192.168.1.1:8096"},
|
||||||
|
{"192.168.1.1:8096/web/index.html", "http://192.168.1.1:8096"},
|
||||||
|
{"http://192.168.1.1:8096/web/index.html", "http://192.168.1.1:8096"},
|
||||||
|
{"http://192.168.1.1:8096/web/", "http://192.168.1.1:8096"},
|
||||||
|
{"http://192.168.1.1:8096/web", "http://192.168.1.1:8096"},
|
||||||
|
{"https://jellyfin.example.com/web/index.html", "https://jellyfin.example.com"},
|
||||||
|
{"https://jellyfin.example.com/web/", "https://jellyfin.example.com"},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
got := NormalizeJellyfinURL(tt.input)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("NormalizeJellyfinURL(%q) = %q, want %q", tt.input, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user