Serve artist placeholder directly, instead of using LastFM's CDN

This commit is contained in:
Deluan 2022-12-30 20:14:03 -05:00
parent b8c171d3d4
commit 6260927074
6 changed files with 79 additions and 12 deletions

View File

@ -3,21 +3,22 @@ package agents
import (
"context"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/model"
)
const PlaceholderAgentName = "placeholder"
const (
placeholderArtistImageSmallUrl = "https://lastfm.freetls.fastly.net/i/u/64s/2a96cbd8b46e442fc41c2b86b821562f.png"
placeholderArtistImageMediumUrl = "https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png"
placeholderArtistImageLargeUrl = "https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png"
placeholderArtistImageSmallUrl = consts.URLPathUI + "/artist-placeholder.webp"
placeholderArtistImageMediumUrl = consts.URLPathUI + "/artist-placeholder.webp"
placeholderArtistImageLargeUrl = consts.URLPathUI + "/artist-placeholder.webp"
placeholderBiography = "Biography not available"
)
type placeholderAgent struct{}
func placeholdersConstructor(ds model.DataStore) Interface {
func placeholdersConstructor(_ model.DataStore) Interface {
return &placeholderAgent{}
}

View File

@ -115,7 +115,7 @@ func compressMiddleware() func(http.Handler) http.Handler {
)
}
func clientUniqueIdAdder(next http.Handler) http.Handler {
func clientUniqueIDMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
clientUniqueId := r.Header.Get(consts.UIClientUniqueIDHeader)
@ -145,3 +145,57 @@ func clientUniqueIdAdder(next http.Handler) http.Handler {
next.ServeHTTP(w, r)
})
}
func serverAddressMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if rScheme, rHost := serverAddress(r); rHost != "" {
r.Host = rHost
r.URL.Scheme = rScheme
}
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
var (
xForwardedHost = http.CanonicalHeaderKey("X-Forwarded-Host")
xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Scheme")
xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Proto")
)
func serverAddress(r *http.Request) (scheme, host string) {
origHost := r.Host
protocol := "http"
if r.TLS != nil {
protocol = "https"
}
xfh := r.Header.Get(xForwardedHost)
if xfh != "" {
i := strings.Index(xfh, ",")
if i == -1 {
i = len(xfh)
}
xfh = xfh[:i]
}
scheme = firstOr(
protocol,
r.Header.Get(xForwardedProto),
r.Header.Get(xForwardedScheme),
r.URL.Scheme,
)
host = firstOr(r.Host, xfh)
if host != origHost {
log.Trace(r.Context(), "Request host has changed", "origHost", origHost, "host", host, "scheme", scheme, "url", r.URL)
}
return scheme, host
}
func firstOr(or string, strings ...string) string {
for _, s := range strings {
if s != "" {
return s
}
}
return or
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"path"
"strings"
"time"
"github.com/go-chi/chi/v5"
@ -94,7 +95,8 @@ func (s *Server) initRoutes() {
r.Use(middleware.Recoverer)
r.Use(compressMiddleware())
r.Use(middleware.Heartbeat("/ping"))
r.Use(clientUniqueIdAdder)
r.Use(serverAddressMiddleware)
r.Use(clientUniqueIDMiddleware)
r.Use(loggerInjector)
r.Use(requestLogger)
r.Use(robotsTXT(ui.BuildAssets()))
@ -135,3 +137,11 @@ func (s *Server) frontendAssetsHandler() http.Handler {
r.Handle("/*", http.StripPrefix(s.appRoot, http.FileServer(http.FS(ui.BuildAssets()))))
return r
}
func AbsoluteURL(r *http.Request, url string) string {
if strings.HasPrefix(url, "/") {
appRoot := path.Join(r.Host, conf.Server.BaseURL, url)
url = r.URL.Scheme + "://" + appRoot
}
return url
}

View File

@ -10,6 +10,7 @@ import (
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/server"
"github.com/navidrome/navidrome/server/subsonic/filter"
"github.com/navidrome/navidrome/server/subsonic/responses"
"github.com/navidrome/navidrome/utils"
@ -231,9 +232,9 @@ func (api *Router) GetArtistInfo(r *http.Request) (*responses.Subsonic, error) {
response := newResponse()
response.ArtistInfo = &responses.ArtistInfo{}
response.ArtistInfo.Biography = artist.Biography
response.ArtistInfo.SmallImageUrl = artist.SmallImageUrl
response.ArtistInfo.MediumImageUrl = artist.MediumImageUrl
response.ArtistInfo.LargeImageUrl = artist.LargeImageUrl
response.ArtistInfo.SmallImageUrl = server.AbsoluteURL(r, artist.SmallImageUrl)
response.ArtistInfo.MediumImageUrl = server.AbsoluteURL(r, artist.MediumImageUrl)
response.ArtistInfo.LargeImageUrl = server.AbsoluteURL(r, artist.LargeImageUrl)
response.ArtistInfo.LastFmUrl = artist.ExternalUrl
response.ArtistInfo.MusicBrainzID = artist.MbzArtistID
for _, s := range artist.SimilarArtists {
@ -259,7 +260,7 @@ func (api *Router) GetArtistInfo2(r *http.Request) (*responses.Subsonic, error)
similar.AlbumCount = s.AlbumCount
similar.Starred = s.Starred
similar.UserRating = s.UserRating
similar.ArtistImageUrl = s.ArtistImageUrl
similar.ArtistImageUrl = server.AbsoluteURL(r, s.ArtistImageUrl)
response.ArtistInfo2.SimilarArtist = append(response.ArtistInfo2.SimilarArtist, similar)
}
return response, nil

View File

@ -78,8 +78,9 @@ type Artist struct {
Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
UserRating int `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
ArtistImageUrl string `xml:"artistImageUrl,attr,omitempty" json:"artistImageUrl,omitempty"`
/*
<xs:attribute name="averageRating" type="sub:AverageRating" use="optional"/> <!-- Added in 1.13.0 -->
/* TODO:
<xs:attribute name="coverArt" type="xs:string" use="optional"/>
<xs:attribute name="averageRating" type="sub:AverageRating" use="optional"/> <!-- Added in 1.13.0 -->
*/
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B