diff --git a/architecture/jamendo-provider.md b/architecture/jamendo-provider.md index 5037bc1..47866e1 100644 --- a/architecture/jamendo-provider.md +++ b/architecture/jamendo-provider.md @@ -55,6 +55,11 @@ Objects (fields we read): - **album**: `id`, `name`, `artist_name`; `/albums/tracks` returns the album wrapping a `tracks[]` array of the same track shape. +**A `User-Agent` header is mandatory** (live-discovered 2026-07-24): Jamendo's +API returns HTTP 200 `success` with an **empty** result set to any request that +carries none — and `reqwest` sends none by default — so `JamApi` sets one. This +is silent (no error), so a missing UA looks exactly like "no matches". + Search parameters: `search` (free text across track/album/artist/tags), `namesearch` (name match), `tags` (AND) / `fuzzytags` (fuzzy OR), `order` (relevance, popularity, downloads, listens, releasedate, …). v1 uses diff --git a/jamendody/src/api.rs b/jamendody/src/api.rs index a58fce6..995f8c2 100644 --- a/jamendody/src/api.rs +++ b/jamendody/src/api.rs @@ -127,6 +127,10 @@ impl JamApi { ) -> Result { let http = reqwest::Client::builder() .timeout(timeout) + // Jamendo's API silently returns HTTP 200 with an empty result set + // (results_count: 0) to requests that carry no User-Agent — reqwest + // sends none by default — so a UA is mandatory, not cosmetic. + .user_agent(concat!("Mozilla/5.0 crabidy/", env!("CARGO_PKG_VERSION"))) .build() .map_err(|err| FetchError::Http(err.to_string()))?; Ok(Self {