From b952e1108a2b713c2ab5ae40938b54cdfe0c4faf Mon Sep 17 00:00:00 2001 From: Cyborus Date: Sun, 10 Dec 2023 00:53:52 -0500 Subject: [PATCH] include body in `ForgejoError::BadStructure` --- Cargo.lock | 1 + Cargo.toml | 1 + src/lib.rs | 28 +++++++++++++--------------- tests/ci_test.rs | 5 +++++ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 436e2be..c3f06ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,6 +174,7 @@ dependencies = [ "git2", "reqwest", "serde", + "serde_json", "soft_assert", "thiserror", "time", diff --git a/Cargo.toml b/Cargo.toml index 6989702..ad84340 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ tokio = { version = "1.29.1", features = ["net"] } url = { version = "2.4.0", features = ["serde"] } serde = { version = "1.0.168", features = ["derive"] } time = { version = "0.3.22", features = ["parsing", "serde", "formatting"] } +serde_json = "1.0.108" [dev-dependencies] eyre = "0.6.9" diff --git a/src/lib.rs b/src/lib.rs index a6a7daf..6d0aa89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,28 +30,18 @@ pub enum ForgejoError { HostRequired, #[error("scheme must be http or https")] HttpRequired, - #[error("{0}")] // for some reason, you can't use `source` and `transparent` together - ReqwestError(#[source] reqwest::Error), + #[error(transparent)] + ReqwestError(#[from] reqwest::Error), #[error("API key should be ascii")] KeyNotAscii, #[error("the response from forgejo was not properly structured")] - BadStructure(#[source] reqwest::Error), + BadStructure(#[source] serde_json::Error, String), #[error("unexpected status code {} {}", .0.as_u16(), .0.canonical_reason().unwrap_or(""))] UnexpectedStatusCode(StatusCode), #[error("{} {}: {}", .0.as_u16(), .0.canonical_reason().unwrap_or(""), .1)] ApiError(StatusCode, String), } -impl From for ForgejoError { - fn from(e: reqwest::Error) -> Self { - if e.is_decode() { - ForgejoError::BadStructure(e) - } else { - ForgejoError::ReqwestError(e) - } - } -} - impl Forgejo { pub fn new(api_key: &str, url: Url) -> Result { Self::with_user_agent(api_key, url, "forgejo-api-rs") @@ -163,7 +153,11 @@ impl Forgejo { async fn execute(&self, request: Request) -> Result { let response = self.client.execute(request).await?; match response.status() { - status if status.is_success() => Ok(response.json::().await?), + status if status.is_success() => { + let body = response.text().await?; + let out = serde_json::from_str(&body).map_err(|e| ForgejoError::BadStructure(e, body))?; + Ok(out) + }, status if status.is_client_error() => Err(ForgejoError::ApiError( status, response.json::().await?.message, @@ -192,7 +186,11 @@ impl Forgejo { ) -> Result, ForgejoError> { let response = self.client.execute(request).await?; match response.status() { - status if status.is_success() => Ok(Some(response.json::().await?)), + status if status.is_success() => { + let body = response.text().await?; + let out = serde_json::from_str(&body).map_err(|e| ForgejoError::BadStructure(e, body))?; + Ok(out) + }, StatusCode::NOT_FOUND => Ok(None), status if status.is_client_error() => Err(ForgejoError::ApiError( status, diff --git a/tests/ci_test.rs b/tests/ci_test.rs index 1017765..9c5d8b5 100644 --- a/tests/ci_test.rs +++ b/tests/ci_test.rs @@ -17,6 +17,11 @@ async fn ci() -> eyre::Result<()> { errors += 1; for (i, err) in report.chain().enumerate() { println!("{i}. {err}"); + if let Some(err) = err.downcast_ref::() { + if let forgejo_api::ForgejoError::BadStructure(_, body) = err { + println!("BODY: {body}"); + } + } } } if errors > 0 {