mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-01 19:47:37 +03:00
Fix background images when BaseURL is specified
This commit is contained in:
parent
d8c5944ef1
commit
03640ca93d
9 changed files with 115 additions and 28 deletions
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
|
@ -91,7 +92,7 @@ func startServer(ctx context.Context) func() error {
|
|||
if conf.Server.Prometheus.Enabled {
|
||||
a.MountRouter("Prometheus metrics", conf.Server.Prometheus.MetricsPath, promhttp.Handler())
|
||||
}
|
||||
if conf.Server.UILoginBackgroundURL == consts.DefaultUILoginBackgroundURL {
|
||||
if strings.HasPrefix(conf.Server.UILoginBackgroundURL, "/") {
|
||||
a.MountRouter("Background images", consts.DefaultUILoginBackgroundURL, backgrounds.NewHandler())
|
||||
}
|
||||
return a.Run(ctx, fmt.Sprintf("%s:%d", conf.Server.Address, conf.Server.Port))
|
||||
|
|
10
conf/configtest/configtest.go
Normal file
10
conf/configtest/configtest.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
package configtest
|
||||
|
||||
import "github.com/navidrome/navidrome/conf"
|
||||
|
||||
func SetupConfig() func() {
|
||||
oldValues := *conf.Server
|
||||
return func() {
|
||||
conf.Server = &oldValues
|
||||
}
|
||||
}
|
2
go.mod
2
go.mod
|
@ -47,6 +47,7 @@ require (
|
|||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/text v0.4.0
|
||||
golang.org/x/tools v0.3.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -236,7 +237,6 @@ require (
|
|||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
honnef.co/go/tools v0.3.3 // indirect
|
||||
mvdan.cc/gofumpt v0.4.0 // indirect
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
|
||||
|
|
|
@ -5,17 +5,16 @@ import (
|
|||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
|
@ -31,7 +30,7 @@ func NewHandler() *Handler {
|
|||
return h
|
||||
}
|
||||
|
||||
const ndImageServiceURL = "https://www.navidrome.org"
|
||||
const ndImageServiceURL = "https://www.navidrome.org/images"
|
||||
|
||||
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
image, err := h.getRandomImage(r.Context())
|
||||
|
@ -42,7 +41,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, buildPath(ndImageServiceURL, "backgrounds", image+".jpg"), http.StatusFound)
|
||||
http.Redirect(w, r, buildPath(ndImageServiceURL, image), http.StatusFound)
|
||||
}
|
||||
|
||||
func (h *Handler) getRandomImage(ctx context.Context) (string, error) {
|
||||
|
@ -73,15 +72,15 @@ func (h *Handler) getImageList(ctx context.Context) ([]string, error) {
|
|||
Timeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, buildPath(ndImageServiceURL, "images"), nil)
|
||||
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, buildPath(ndImageServiceURL, "index.yml"), nil)
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
log.Warn(ctx, "Could not get list from image service", err)
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
h.list = strings.Split(string(body), "\n")
|
||||
dec := yaml.NewDecoder(resp.Body)
|
||||
err = dec.Decode(&h.list)
|
||||
log.Debug(ctx, "Loaded images from image service", "total", len(h.list), "elapsed", time.Since(start))
|
||||
return h.list, err
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
|
@ -53,6 +54,9 @@ func serveIndex(ds model.DataStore, fs fs.FS) http.HandlerFunc {
|
|||
"devShowArtistPage": conf.Server.DevShowArtistPage,
|
||||
"listenBrainzEnabled": conf.Server.ListenBrainz.Enabled,
|
||||
}
|
||||
if strings.HasPrefix(conf.Server.UILoginBackgroundURL, "/") {
|
||||
appConfig["loginBackgroundURL"] = path.Join(conf.Server.BaseURL, conf.Server.UILoginBackgroundURL)
|
||||
}
|
||||
auth := handleLoginFromHeaders(ds, r)
|
||||
if auth != nil {
|
||||
appConfig["auth"] = auth
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/conf/configtest"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/tests"
|
||||
|
@ -24,7 +25,7 @@ var _ = Describe("serveIndex", func() {
|
|||
|
||||
BeforeEach(func() {
|
||||
ds = &tests.MockDataStore{MockedUser: mockUser}
|
||||
conf.Server.UILoginBackgroundURL = ""
|
||||
DeferCleanup(configtest.SetupConfig())
|
||||
})
|
||||
|
||||
It("adds app_config to index.html", func() {
|
||||
|
@ -82,17 +83,6 @@ var _ = Describe("serveIndex", func() {
|
|||
Expect(config).To(HaveKeyWithValue("baseURL", "base_url_test"))
|
||||
})
|
||||
|
||||
It("sets the uiLoginBackgroundURL", func() {
|
||||
conf.Server.UILoginBackgroundURL = "my_background_url"
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
serveIndex(ds, fs)(w, r)
|
||||
|
||||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("loginBackgroundURL", "my_background_url"))
|
||||
})
|
||||
|
||||
It("sets the welcomeMessage", func() {
|
||||
conf.Server.UIWelcomeMessage = "Hello"
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
|
@ -298,9 +288,94 @@ var _ = Describe("serveIndex", func() {
|
|||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("listenBrainzEnabled", true))
|
||||
})
|
||||
|
||||
Describe("loginBackgroundURL", func() {
|
||||
Context("empty BaseURL", func() {
|
||||
BeforeEach(func() {
|
||||
conf.Server.BaseURL = "/"
|
||||
})
|
||||
When("it is the default URL", func() {
|
||||
It("points to the default URL", func() {
|
||||
conf.Server.UILoginBackgroundURL = consts.DefaultUILoginBackgroundURL
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
serveIndex(ds, fs)(w, r)
|
||||
|
||||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("loginBackgroundURL", consts.DefaultUILoginBackgroundURL))
|
||||
})
|
||||
})
|
||||
When("it is the default offline URL", func() {
|
||||
It("points to the offline URL", func() {
|
||||
conf.Server.UILoginBackgroundURL = consts.DefaultUILoginBackgroundURLOffline
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
serveIndex(ds, fs)(w, r)
|
||||
|
||||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("loginBackgroundURL", consts.DefaultUILoginBackgroundURLOffline))
|
||||
})
|
||||
})
|
||||
When("it is a custom URL", func() {
|
||||
It("points to the offline URL", func() {
|
||||
conf.Server.UILoginBackgroundURL = "https://example.com/images/1.jpg"
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
serveIndex(ds, fs)(w, r)
|
||||
|
||||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("loginBackgroundURL", "https://example.com/images/1.jpg"))
|
||||
})
|
||||
})
|
||||
})
|
||||
Context("with a BaseURL", func() {
|
||||
BeforeEach(func() {
|
||||
conf.Server.BaseURL = "/music"
|
||||
})
|
||||
When("it is the default URL", func() {
|
||||
It("points to the default URL with BaseURL prefix", func() {
|
||||
conf.Server.UILoginBackgroundURL = consts.DefaultUILoginBackgroundURL
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
serveIndex(ds, fs)(w, r)
|
||||
|
||||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("loginBackgroundURL", "/music"+consts.DefaultUILoginBackgroundURL))
|
||||
})
|
||||
})
|
||||
When("it is the default offline URL", func() {
|
||||
It("points to the offline URL", func() {
|
||||
conf.Server.UILoginBackgroundURL = consts.DefaultUILoginBackgroundURLOffline
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
serveIndex(ds, fs)(w, r)
|
||||
|
||||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("loginBackgroundURL", consts.DefaultUILoginBackgroundURLOffline))
|
||||
})
|
||||
})
|
||||
When("it is a custom URL", func() {
|
||||
It("points to the offline URL", func() {
|
||||
conf.Server.UILoginBackgroundURL = "https://example.com/images/1.jpg"
|
||||
r := httptest.NewRequest("GET", "/index.html", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
serveIndex(ds, fs)(w, r)
|
||||
|
||||
config := extractAppConfig(w.Body.String())
|
||||
Expect(config).To(HaveKeyWithValue("loginBackgroundURL", "https://example.com/images/1.jpg"))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var appConfigRegex = regexp.MustCompile(`(?m)window.__APP_CONFIG__="([^"]*)`)
|
||||
var appConfigRegex = regexp.MustCompile(`(?m)window.__APP_CONFIG__=(.*);</script>`)
|
||||
|
||||
func extractAppConfig(body string) map[string]interface{} {
|
||||
config := make(map[string]interface{})
|
||||
|
@ -308,7 +383,7 @@ func extractAppConfig(body string) map[string]interface{} {
|
|||
if match == nil {
|
||||
return config
|
||||
}
|
||||
str, err := strconv.Unquote("\"" + match[1] + "\"")
|
||||
str, err := strconv.Unquote(match[1])
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("%s: %s", match[1], err))
|
||||
}
|
||||
|
|
5
tests/fixtures/index.html
vendored
5
tests/fixtures/index.html
vendored
|
@ -7,9 +7,8 @@
|
|||
content="Navidrome Music Server - {{.Version}}"
|
||||
/>
|
||||
<title>Navidrome</title>
|
||||
<script>
|
||||
window.__APP_CONFIG__="{{.AppConfig}}"
|
||||
</script>
|
||||
<!-- The line below has to match the exact format of the equivalent line in ui/build/index.html -->
|
||||
<script>window.__APP_CONFIG__={{ .AppConfig }};</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
-->
|
||||
<title>Navidrome</title>
|
||||
<script>
|
||||
window.__APP_CONFIG__ = "{{.AppConfig}}"
|
||||
window.__APP_CONFIG__ = {{ .AppConfig }}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -34,7 +34,6 @@ let config
|
|||
|
||||
try {
|
||||
const appConfig = JSON.parse(window.__APP_CONFIG__)
|
||||
|
||||
config = {
|
||||
...defaultConfig,
|
||||
...appConfig,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue