mirror of
https://github.com/navidrome/navidrome.git
synced 2026-11-05 01:38:51 +01:00
fix(jellyfin): let net/http sniff image Content-Type instead of forcing jpeg
This commit is contained in:
parent
6e4a180feb
commit
926a36acfa
2 changed files with 42 additions and 10 deletions
|
|
@ -2,11 +2,13 @@ package jellyfin
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
)
|
||||
|
||||
|
|
@ -17,12 +19,17 @@ func (api *Router) getItemImage(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
artID := api.resolveArtworkID(ctx, itemId)
|
||||
reader, _, err := api.artwork.GetOrPlaceholder(ctx, artID, size, false)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, context.Canceled):
|
||||
return
|
||||
case err != nil:
|
||||
log.Warn(ctx, "Error retrieving artwork", "id", itemId, err)
|
||||
http.Error(w, "Not Found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
defer reader.Close()
|
||||
w.Header().Set("Content-Type", "image/jpeg")
|
||||
// Content-Type is left unset so net/http sniffs it from the first bytes written
|
||||
// (placeholders are WebP; unresized covers can be PNG/WebP/etc, not always JPEG).
|
||||
_, _ = io.Copy(w, reader)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package jellyfin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
|
@ -19,11 +19,26 @@ import (
|
|||
type fakeArtwork struct {
|
||||
artwork.Artwork
|
||||
recvId string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (f *fakeArtwork) GetOrPlaceholder(ctx context.Context, id string, size int, square bool) (io.ReadCloser, time.Time, error) {
|
||||
f.recvId = id
|
||||
return io.NopCloser(strings.NewReader("IMG")), time.Now(), nil
|
||||
data := f.data
|
||||
if data == nil {
|
||||
data = []byte("IMG")
|
||||
}
|
||||
return io.NopCloser(bytes.NewReader(data)), time.Now(), nil
|
||||
}
|
||||
|
||||
func newImageRequest(itemId string) (*httptest.ResponseRecorder, *http.Request) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/Items/"+itemId+"/Images/Primary", nil)
|
||||
rctx := chi.NewRouteContext()
|
||||
rctx.URLParams.Add("itemId", itemId)
|
||||
rctx.URLParams.Add("type", "Primary")
|
||||
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
|
||||
return w, r
|
||||
}
|
||||
|
||||
var _ = Describe("Images", func() {
|
||||
|
|
@ -33,16 +48,26 @@ var _ = Describe("Images", func() {
|
|||
fa := &fakeArtwork{}
|
||||
api := &Router{ds: ds, artwork: fa}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/Items/a1/Images/Primary", nil)
|
||||
rctx := chi.NewRouteContext()
|
||||
rctx.URLParams.Add("itemId", "a1")
|
||||
rctx.URLParams.Add("type", "Primary")
|
||||
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
|
||||
w, r := newImageRequest("a1")
|
||||
api.getItemImage(w, r)
|
||||
|
||||
Expect(w.Code).To(Equal(http.StatusOK))
|
||||
Expect(w.Body.String()).To(Equal("IMG"))
|
||||
Expect(fa.recvId).To(ContainSubstring("a1"))
|
||||
})
|
||||
|
||||
It("sniffs the Content-Type instead of hardcoding it", func() {
|
||||
ds := &tests.MockDataStore{}
|
||||
ds.Album(context.Background()).(*tests.MockAlbumRepo).SetData(model.Albums{{ID: "a1", Name: "One"}})
|
||||
|
||||
png := append([]byte{0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n'}, make([]byte, 512)...)
|
||||
fa := &fakeArtwork{data: png}
|
||||
api := &Router{ds: ds, artwork: fa}
|
||||
|
||||
w, r := newImageRequest("a1")
|
||||
api.getItemImage(w, r)
|
||||
|
||||
Expect(w.Code).To(Equal(http.StatusOK))
|
||||
Expect(w.Header().Get("Content-Type")).To(Equal("image/png"))
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue