add back image fetch failure handling

idiot api gives 200 json
This commit is contained in:
psykose 2024-11-19 13:57:25 +01:00
parent 4e078a857a
commit c7c844f2f0
Signed by: psykose
SSH key fingerprint: SHA256:pRMVjV3kRB6zl+wNx+sV8KoMnPqQAW6v8dNCxsCGZv8

View file

@ -80,6 +80,11 @@ pub struct Client {
base_url: reqwest::Url, base_url: reqwest::Url,
} }
struct ByteResponse {
bytes: Bytes,
content_type: String,
}
fn random_salt(length: usize) -> String { fn random_salt(length: usize) -> String {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
std::iter::repeat(()) std::iter::repeat(())
@ -155,7 +160,10 @@ impl Client {
Ok(Client { client, base_url }) Ok(Client { client, base_url })
} }
async fn send(&self, request: reqwest_middleware::RequestBuilder) -> Result<Bytes, Error> { async fn send(
&self,
request: reqwest_middleware::RequestBuilder,
) -> Result<ByteResponse, Error> {
// FIXME: is an entire channel per request overkill? maybe pool them? // FIXME: is an entire channel per request overkill? maybe pool them?
let (sender, receiver) = async_channel::bounded(1); let (sender, receiver) = async_channel::bounded(1);
@ -168,12 +176,15 @@ impl Client {
// wrap this logic in a fn so we can use ? // wrap this logic in a fn so we can use ?
async fn perform( async fn perform(
response: Result<reqwest::Response, reqwest_middleware::Error>, response: Result<reqwest::Response, reqwest_middleware::Error>,
) -> Result<Bytes, Error> { ) -> Result<ByteResponse, Error> {
let response = response?.error_for_status()?; let response = response?.error_for_status()?;
let xcache = response.headers()[http_cache::XCACHE].to_str().ok(); let xcache = response.headers()[http_cache::XCACHE].to_str().ok();
let content_type = response.headers()[reqwest::header::CONTENT_TYPE] let content_type = String::from_utf8(
.to_str() response.headers()[reqwest::header::CONTENT_TYPE]
.ok(); .as_bytes()
.to_vec(),
)
.expect("invalid content type (required)");
event!( event!(
name: "response", name: "response",
target: "audrey::http", target: "audrey::http",
@ -181,12 +192,16 @@ impl Client {
url=response.url().as_str(), url=response.url().as_str(),
status=response.status().as_str(), status=response.status().as_str(),
cache_status=xcache, cache_status=xcache,
content_type=content_type content_type=&content_type
); );
response let bytes = response
.bytes() .bytes()
.await .await
.map_err(|e| Error::ReqwestError(reqwest_middleware::Error::Reqwest(e))) .map_err(|e| Error::ReqwestError(reqwest_middleware::Error::Reqwest(e)))?;
Ok(ByteResponse {
bytes,
content_type,
})
} }
sender sender
@ -211,7 +226,7 @@ impl Client {
url url
} }
async fn get_bytes(&self, url: url::Url) -> Result<Bytes, Error> { async fn get_bytes(&self, url: url::Url) -> Result<ByteResponse, Error> {
self.send(self.client.get(url)).await self.send(self.client.get(url)).await
} }
@ -219,8 +234,8 @@ impl Client {
&self, &self,
url: url::Url, url: url::Url,
) -> Result<T, Error> { ) -> Result<T, Error> {
let bytes = self.get_bytes(url).await?; let byteresponse = self.get_bytes(url).await?;
serde_json::from_slice::<T>(&bytes).map_err(Error::JsonDecodeError) serde_json::from_slice::<T>(&byteresponse.bytes).map_err(Error::JsonDecodeError)
} }
async fn get_subsonic<T: serde::de::DeserializeOwned + Send + 'static>( async fn get_subsonic<T: serde::de::DeserializeOwned + Send + 'static>(
@ -266,9 +281,19 @@ impl Client {
size: Option<u32>, size: Option<u32>,
) -> Result<gtk::gdk_pixbuf::Pixbuf, Error> { ) -> Result<gtk::gdk_pixbuf::Pixbuf, Error> {
let url = self.cover_art_url(id, size); let url = self.cover_art_url(id, size);
let cover_art_bytes = self.get_bytes(url).await?; let byteresponse = self.get_bytes(url).await?;
if byteresponse.content_type == "application/json" {
let json =
serde_json::from_slice::<schema::SubsonicResponseOuter<()>>(&byteresponse.bytes)
.map_err(Error::JsonDecodeError)?;
let error = match json.subsonic_response {
schema::SubsonicResponse::Failed { error } => Err(Error::SubsonicError(error)),
_ => panic!("error response didn't get parsed as error"),
};
return error;
}
let image = ImageReader::new(std::io::BufReader::new(std::io::Cursor::new( let image = ImageReader::new(std::io::BufReader::new(std::io::Cursor::new(
cover_art_bytes, byteresponse.bytes,
))) )))
.with_guessed_format() .with_guessed_format()
.map_err(|e| Error::ImageDecodeError(image::ImageError::IoError(e)))? .map_err(|e| Error::ImageDecodeError(image::ImageError::IoError(e)))?