mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-31 07:30:32 +00:00
Finamp's connection test GETs /System/Endpoint and treats anything other than a 200 carrying an IsInNetwork key as "not a Jellyfin server", so the test failed against Navidrome and dual-connection setups could never switch to the local address. IsInNetwork mirrors Jellyfin's default LAN set (NetworkManager with no LocalNetworkSubnets configured): loopback, the RFC 1918 ranges, fc00::/7 and fe80::/10. Notably that set omits 169.254.0.0/16, so Go's IsLinkLocalUnicast is deliberately restricted to its IPv6 half. IsLocal mirrors HttpContext.IsLocal(): the caller shares the connection's local address, not merely "is loopback". It falls back to the loopback check when the local address is unavailable.
93 lines
2.8 KiB
Go
93 lines
2.8 KiB
Go
package e2e
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("System", func() {
|
|
BeforeEach(func() { setupTestDB() })
|
|
|
|
Describe("GET /System/Info/Public", func() {
|
|
It("returns public server info without authentication", func() {
|
|
w := rawReq("GET", "/System/Info/Public", "")
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
var info map[string]any
|
|
parseInto(w, &info)
|
|
Expect(info["ServerName"]).To(HavePrefix("Navidrome"))
|
|
Expect(info["ProductName"]).To(Equal("Jellyfin Server"))
|
|
Expect(info["StartupWizardCompleted"]).To(BeTrue())
|
|
Expect(info["Id"]).ToNot(BeEmpty())
|
|
Expect(info["Version"]).ToNot(BeEmpty())
|
|
})
|
|
|
|
It("routes case-insensitively (lowercase path)", func() {
|
|
w := rawReq("GET", "/system/info/public", "")
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
})
|
|
})
|
|
|
|
Describe("GET /System/Info", func() {
|
|
It("returns system info to any authenticated user, matching the public Version", func() {
|
|
w := getAs(regularUser, "/System/Info")
|
|
var info map[string]any
|
|
parseInto(w, &info)
|
|
Expect(info["Version"]).ToNot(BeEmpty())
|
|
Expect(info["SupportsLibraryMonitor"]).To(BeTrue())
|
|
|
|
pub := rawReq("GET", "/System/Info/Public", "")
|
|
var pubInfo map[string]any
|
|
parseInto(pub, &pubInfo)
|
|
Expect(info["Version"]).To(Equal(pubInfo["Version"]))
|
|
Expect(info["Id"]).To(Equal(pubInfo["Id"]))
|
|
})
|
|
|
|
It("rejects unauthenticated requests", func() {
|
|
w := rawReq("GET", "/System/Info", "")
|
|
Expect(w.Code).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Describe("GET /System/Endpoint", func() {
|
|
It("always reports IsInNetwork, which Finamp's connection test probes for", func() {
|
|
w := getAs(regularUser, "/System/Endpoint")
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
var info map[string]any
|
|
parseInto(w, &info)
|
|
Expect(info).To(HaveKey("IsInNetwork"))
|
|
Expect(info).To(HaveKey("IsLocal"))
|
|
})
|
|
|
|
It("rejects unauthenticated requests", func() {
|
|
w := rawReq("GET", "/System/Endpoint", "")
|
|
Expect(w.Code).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Describe("GET/POST /System/Ping", func() {
|
|
It("answers GET with a plain-text server name", func() {
|
|
w := rawReq("GET", "/System/Ping", "")
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
Expect(w.Header().Get("Content-Type")).To(HavePrefix("text/plain"))
|
|
Expect(w.Body.String()).To(HavePrefix("Navidrome"))
|
|
})
|
|
|
|
It("answers POST identically", func() {
|
|
w := rawReq("POST", "/System/Ping", "")
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
Expect(strings.TrimSpace(w.Body.String())).To(HavePrefix("Navidrome"))
|
|
})
|
|
})
|
|
|
|
Describe("GET /QuickConnect/Enabled", func() {
|
|
It("reports QuickConnect disabled", func() {
|
|
w := rawReq("GET", "/QuickConnect/Enabled", "")
|
|
Expect(w.Code).To(Equal(http.StatusOK))
|
|
Expect(strings.TrimSpace(w.Body.String())).To(Equal("false"))
|
|
})
|
|
})
|
|
})
|