diff --git a/allstarr/Controllers/JellyfinController.cs b/allstarr/Controllers/JellyfinController.cs index 4b540c1..b9668f8 100644 --- a/allstarr/Controllers/JellyfinController.cs +++ b/allstarr/Controllers/JellyfinController.cs @@ -2823,15 +2823,15 @@ public class JellyfinController : ControllerBase // Include UserId parameter to avoid 401 Unauthorized var userId = _settings.UserId; var playlistItemsUrl = $"Playlists/{playlistId}/Items"; + var queryParams = new Dictionary(); if (!string.IsNullOrEmpty(userId)) { - playlistItemsUrl += $"?UserId={userId}"; + queryParams["UserId"] = userId; } - var (localTracksResponse, _) = await _proxyService.GetJsonAsync( + var (localTracksResponse, _) = await _proxyService.GetJsonAsyncInternal( playlistItemsUrl, - null, - Request.Headers); + queryParams); if (localTracksResponse != null && localTracksResponse.RootElement.TryGetProperty("Items", out var localItems)) diff --git a/allstarr/Services/Jellyfin/JellyfinProxyService.cs b/allstarr/Services/Jellyfin/JellyfinProxyService.cs index 187a7a8..80e0846 100644 --- a/allstarr/Services/Jellyfin/JellyfinProxyService.cs +++ b/allstarr/Services/Jellyfin/JellyfinProxyService.cs @@ -967,4 +967,43 @@ public class JellyfinProxyService return url; } + + /// + /// Sends a GET request to the Jellyfin server using the server's API key for internal operations. + /// This should only be used for server-side operations, not for proxying client requests. + /// + public async Task<(JsonDocument? Body, int StatusCode)> GetJsonAsyncInternal(string endpoint, Dictionary? queryParams = null) + { + var url = BuildUrl(endpoint, queryParams); + + using var request = new HttpRequestMessage(HttpMethod.Get, url); + + // Use server's API key for authentication + var authHeader = GetAuthorizationHeader(); + request.Headers.TryAddWithoutValidation("X-Emby-Authorization", authHeader); + + request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + var response = await _httpClient.SendAsync(request); + var statusCode = (int)response.StatusCode; + var content = await response.Content.ReadAsStringAsync(); + + if (!response.IsSuccessStatusCode) + { + _logger.LogWarning("Jellyfin internal request returned {StatusCode} for {Url}: {Content}", + statusCode, url, content); + return (null, statusCode); + } + + try + { + var jsonDocument = JsonDocument.Parse(content); + return (jsonDocument, statusCode); + } + catch (JsonException ex) + { + _logger.LogError(ex, "Failed to parse JSON response from {Url}: {Content}", url, content); + return (null, statusCode); + } + } }