diff --git a/Cargo.lock b/Cargo.lock index 4d4af7c..7b7acd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,6 +445,7 @@ dependencies = [ "thiserror", "tokio", "tracing", + "unicode-bom", ] [[package]] @@ -1419,6 +1420,12 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +[[package]] +name = "unicode-bom" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" + [[package]] name = "unicode-ident" version = "1.0.8" diff --git a/gha-cache/Cargo.toml b/gha-cache/Cargo.toml index 088c881..8a0da8e 100644 --- a/gha-cache/Cargo.toml +++ b/gha-cache/Cargo.toml @@ -16,6 +16,7 @@ serde_json = "1.0.96" sha2 = "0.10.6" thiserror = "1.0.40" tracing = "0.1.37" +unicode-bom = "2.0.2" [dependencies.tokio] version = "1.28.0" diff --git a/gha-cache/src/api.rs b/gha-cache/src/api.rs index 3a3b1d7..6d368a9 100644 --- a/gha-cache/src/api.rs +++ b/gha-cache/src/api.rs @@ -19,6 +19,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; use sha2::{Digest, Sha256}; use thiserror::Error; use tokio::{io::AsyncRead, sync::Semaphore}; +use unicode_bom::Bom; use crate::credentials::Credentials; use crate::util::read_chunk_async; @@ -525,16 +526,21 @@ impl ResponseExt for reqwest::Response { async fn handle_error(res: reqwest::Response) -> Error { let status = res.status(); let bytes = match res.bytes().await { - Ok(bytes) => bytes, + Ok(bytes) => { + let bom = Bom::from(bytes.as_ref()); + bytes.slice(bom.len()..) + } Err(e) => { return e.into(); } }; - let info = if let Ok(structured) = serde_json::from_slice(&bytes) { - ApiErrorInfo::Structured(structured) - } else { - ApiErrorInfo::Unstructured(bytes) + let info = match serde_json::from_slice(&bytes) { + Ok(structured) => ApiErrorInfo::Structured(structured), + Err(e) => { + tracing::info!("failed to decode error: {}", e); + ApiErrorInfo::Unstructured(bytes) + } }; Error::ApiError { status, info }