From 4d2196f41da1c6781689105aafe41ed6c0875a38 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Fri, 18 Sep 2026 14:31:03 +0300 Subject: [PATCH] =?UTF-8?q?jellyfin:=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B7=D0=B0=D0=B3=D0=BE?= =?UTF-8?q?=D0=BB=D0=BE=D0=B2=D0=BA=D0=BE=D0=BC=20Authorization=20=D0=B2?= =?UTF-8?q?=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20X-Emby-Token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Jellyfin 12 миграцией выключает legacy-авторизацию, и X-Emby-Token получает 401 — пересканирование медиатеки после раскладки перестаёт работать - схема `MediaBrowser Token="…"` принимается и 10.11, так что деплой можно делать до обновления Jellyfin --- internal/jellyfin/jellyfin.go | 5 ++++- internal/jellyfin/jellyfin_test.go | 12 ++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/jellyfin/jellyfin.go b/internal/jellyfin/jellyfin.go index a17dd57..6fec3cd 100644 --- a/internal/jellyfin/jellyfin.go +++ b/internal/jellyfin/jellyfin.go @@ -78,7 +78,10 @@ func (c *Client) RefreshLibraries(ctx context.Context) error { if err != nil { return fmt.Errorf("jellyfin: build request: %w", err) } - req.Header.Set("X-Emby-Token", c.apiKey) + // Схема MediaBrowser в Authorization — единственный способ авторизации, + // который Jellyfin 12 принимает по умолчанию: X-Emby-Token и прочие + // legacy-заголовки выключены (EnableLegacyAuthorization=false). + req.Header.Set("Authorization", `MediaBrowser Token="`+c.apiKey+`"`) log := logctx.FromOr(ctx, c.log) call := logging.StartCall(logging.ServiceJellyfin, "library/refresh") diff --git a/internal/jellyfin/jellyfin_test.go b/internal/jellyfin/jellyfin_test.go index 83a5e61..f339c7e 100644 --- a/internal/jellyfin/jellyfin_test.go +++ b/internal/jellyfin/jellyfin_test.go @@ -8,11 +8,12 @@ import ( ) func TestRefreshLibraries_OK(t *testing.T) { - var gotPath, gotToken, gotMethod string + var gotPath, gotAuth, gotLegacy, gotMethod string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotMethod = r.Method gotPath = r.URL.Path - gotToken = r.Header.Get("X-Emby-Token") + gotAuth = r.Header.Get("Authorization") + gotLegacy = r.Header.Get("X-Emby-Token") w.WriteHeader(http.StatusNoContent) })) defer srv.Close() @@ -30,8 +31,11 @@ func TestRefreshLibraries_OK(t *testing.T) { if gotPath != "/Library/Refresh" { t.Errorf("path = %q, want /Library/Refresh", gotPath) } - if gotToken != "secret" { - t.Errorf("token = %q, want secret", gotToken) + if want := `MediaBrowser Token="secret"`; gotAuth != want { + t.Errorf("Authorization = %q, want %q", gotAuth, want) + } + if gotLegacy != "" { + t.Errorf("X-Emby-Token = %q, want пусто (legacy-заголовок выключен в Jellyfin 12)", gotLegacy) } }