From c4c968e594edcfce231682db5563f7186da7c6f0 Mon Sep 17 00:00:00 2001 From: Timon de Groot Date: Thu, 7 Aug 2025 12:22:56 +0200 Subject: [PATCH 1/5] spclient: Specify base url for metadata requests This fixes #1527 --- core/src/spclient.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/core/src/spclient.rs b/core/src/spclient.rs index 87a6098..56c4287 100644 --- a/core/src/spclient.rs +++ b/core/src/spclient.rs @@ -55,6 +55,7 @@ const CONNECTION_ID: HeaderName = HeaderName::from_static("x-spotify-connection- const NO_METRICS_AND_SALT: RequestOptions = RequestOptions { metrics: false, salt: false, + base_url: None, }; #[derive(Debug, Error)] @@ -86,6 +87,7 @@ impl Default for RequestStrategy { pub struct RequestOptions { metrics: bool, salt: bool, + base_url: Option, } impl Default for RequestOptions { @@ -93,6 +95,7 @@ impl Default for RequestOptions { Self { metrics: true, salt: true, + base_url: None, } } } @@ -449,7 +452,10 @@ impl SpClient { // Reconnection logic: retrieve the endpoint every iteration, so we can try // another access point when we are experiencing network issues (see below). - let mut url = self.base_url().await?; + let mut url = match &options.base_url { + Some(base_url) => base_url.clone(), + None => self.base_url().await?, + }; url.push_str(endpoint); // Add metrics. There is also an optional `partner` key with a value like @@ -566,7 +572,12 @@ impl SpClient { pub async fn get_metadata(&self, scope: &str, id: &SpotifyId) -> SpClientResult { let endpoint = format!("/metadata/4/{}/{}", scope, id.to_base16()?); - self.request(&Method::GET, &endpoint, None, None).await + let options = RequestOptions { + base_url: Some(String::from("https://spclient.wg.spotify.com")), + ..Default::default() + }; + self.request_with_options(&Method::GET, &endpoint, None, None, &options) + .await } pub async fn get_track_metadata(&self, track_id: &SpotifyId) -> SpClientResult { -- 2.49.0 From 2b72f3fbdf6519321feeaaecc1ea6e1bb042074e Mon Sep 17 00:00:00 2001 From: Timon de Groot Date: Thu, 7 Aug 2025 13:51:55 +0200 Subject: [PATCH 2/5] spclient: Change RequestOptions to &str This will allocate less strings and makes it possible to have const request option values. Also document why the metadata base url workaround is needed. --- core/src/spclient.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/src/spclient.rs b/core/src/spclient.rs index 56c4287..11bcef4 100644 --- a/core/src/spclient.rs +++ b/core/src/spclient.rs @@ -87,7 +87,7 @@ impl Default for RequestStrategy { pub struct RequestOptions { metrics: bool, salt: bool, - base_url: Option, + base_url: Option<&'static str>, } impl Default for RequestOptions { @@ -453,7 +453,7 @@ impl SpClient { // Reconnection logic: retrieve the endpoint every iteration, so we can try // another access point when we are experiencing network issues (see below). let mut url = match &options.base_url { - Some(base_url) => base_url.clone(), + Some(base_url) => base_url.to_owned().to_string(), None => self.base_url().await?, }; url.push_str(endpoint); @@ -572,8 +572,11 @@ impl SpClient { pub async fn get_metadata(&self, scope: &str, id: &SpotifyId) -> SpClientResult { let endpoint = format!("/metadata/4/{}/{}", scope, id.to_base16()?); + // For unknown reasons, metadata requests must now be sent through spclient.wg.spotify.com. + // Otherwise, the API will respond with 500 Internal Server Error responses. + // Context: https://github.com/librespot-org/librespot/issues/1527 let options = RequestOptions { - base_url: Some(String::from("https://spclient.wg.spotify.com")), + base_url: Some("https://spclient.wg.spotify.com"), ..Default::default() }; self.request_with_options(&Method::GET, &endpoint, None, None, &options) -- 2.49.0 From 73ed5c50849bb660834cd0d7aaa7110c01397055 Mon Sep 17 00:00:00 2001 From: Timon de Groot Date: Sat, 9 Aug 2025 09:28:51 +0200 Subject: [PATCH 3/5] spclient: Make const request options for get_metadata --- core/src/spclient.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/core/src/spclient.rs b/core/src/spclient.rs index 11bcef4..cbcf092 100644 --- a/core/src/spclient.rs +++ b/core/src/spclient.rs @@ -58,6 +58,12 @@ const NO_METRICS_AND_SALT: RequestOptions = RequestOptions { base_url: None, }; +const SPCLIENT_FALLBACK_ENDPOINT: RequestOptions = RequestOptions { + metrics: true, + salt: true, + base_url: Some("https://spclient.wg.spotify.com"), +}; + #[derive(Debug, Error)] pub enum SpClientError { #[error("missing attribute {0}")] @@ -575,12 +581,14 @@ impl SpClient { // For unknown reasons, metadata requests must now be sent through spclient.wg.spotify.com. // Otherwise, the API will respond with 500 Internal Server Error responses. // Context: https://github.com/librespot-org/librespot/issues/1527 - let options = RequestOptions { - base_url: Some("https://spclient.wg.spotify.com"), - ..Default::default() - }; - self.request_with_options(&Method::GET, &endpoint, None, None, &options) - .await + self.request_with_options( + &Method::GET, + &endpoint, + None, + None, + &SPCLIENT_FALLBACK_ENDPOINT, + ) + .await } pub async fn get_track_metadata(&self, track_id: &SpotifyId) -> SpClientResult { -- 2.49.0 From 6adca21fdf64bd8026a2d6df04c42dd2b1239358 Mon Sep 17 00:00:00 2001 From: Timon de Groot Date: Sat, 9 Aug 2025 09:40:20 +0200 Subject: [PATCH 4/5] spclient: Simplify base url init --- core/src/spclient.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/spclient.rs b/core/src/spclient.rs index cbcf092..272975d 100644 --- a/core/src/spclient.rs +++ b/core/src/spclient.rs @@ -458,8 +458,8 @@ impl SpClient { // Reconnection logic: retrieve the endpoint every iteration, so we can try // another access point when we are experiencing network issues (see below). - let mut url = match &options.base_url { - Some(base_url) => base_url.to_owned().to_string(), + let mut url = match options.base_url { + Some(base_url) => base_url.to_string(), None => self.base_url().await?, }; url.push_str(endpoint); -- 2.49.0 From 0b5b1eb6c73a9291057b3856939f416113fdd8bb Mon Sep 17 00:00:00 2001 From: Timon de Groot Date: Sat, 9 Aug 2025 10:14:02 +0200 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 560de2b..b62e9f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [connect] Correctly apply playing/paused state when transferring playback - [player] Saturate invalid seek positions to track duration - [audio] Fall back to other URLs in case of a failure when downloading from CDN +- [core] Metadata requests failing with 500 Internal Server Error ### Deprecated -- 2.49.0