From 29ce2e4f4df21155da04ef6a070cd1bb1c4d3187 Mon Sep 17 00:00:00 2001 From: Cesar Rodas Date: Mon, 18 Aug 2025 11:51:24 -0300 Subject: [PATCH] Http retry should only happen at Http Error (which are transport errors) Fixes #939 --- crates/cdk-common/src/error.rs | 4 +- .../src/wallet/mint_connector/http_client.rs | 49 ++++++++++++++----- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/crates/cdk-common/src/error.rs b/crates/cdk-common/src/error.rs index 23aaeb5e..5d19ab4e 100644 --- a/crates/cdk-common/src/error.rs +++ b/crates/cdk-common/src/error.rs @@ -290,8 +290,8 @@ pub enum Error { #[error(transparent)] HexError(#[from] hex::Error), /// Http transport error - #[error("Http transport error: {0}")] - HttpError(String), + #[error("Http transport error {0:?}: {1}")] + HttpError(Option, String), #[cfg(feature = "wallet")] // Crate error conversions /// Cashu Url Error diff --git a/crates/cdk/src/wallet/mint_connector/http_client.rs b/crates/cdk/src/wallet/mint_connector/http_client.rs index 25b0c891..1421ece9 100644 --- a/crates/cdk/src/wallet/mint_connector/http_client.rs +++ b/crates/cdk/src/wallet/mint_connector/http_client.rs @@ -64,10 +64,20 @@ impl HttpClientCore { let response = request .send() .await - .map_err(|e| Error::HttpError(e.to_string()))? + .map_err(|e| { + Error::HttpError( + e.status().map(|status_code| status_code.as_u16()), + e.to_string(), + ) + })? .text() .await - .map_err(|e| Error::HttpError(e.to_string()))?; + .map_err(|e| { + Error::HttpError( + e.status().map(|status_code| status_code.as_u16()), + e.to_string(), + ) + })?; serde_json::from_str::(&response).map_err(|err| { tracing::warn!("Http Response error: {}", err); @@ -90,15 +100,19 @@ impl HttpClientCore { request = request.header(auth.header_key(), auth.to_string()); } - let response = request - .send() - .await - .map_err(|e| Error::HttpError(e.to_string()))?; + let response = request.send().await.map_err(|e| { + Error::HttpError( + e.status().map(|status_code| status_code.as_u16()), + e.to_string(), + ) + })?; - let response = response - .text() - .await - .map_err(|e| Error::HttpError(e.to_string()))?; + let response = response.text().await.map_err(|e| { + Error::HttpError( + e.status().map(|status_code| status_code.as_u16()), + e.to_string(), + ) + })?; serde_json::from_str::(&response).map_err(|err| { tracing::warn!("Http Response error: {}", err); @@ -189,7 +203,12 @@ impl HttpClient { })) .danger_accept_invalid_certs(accept_invalid_certs) // Allow self-signed certs .build() - .map_err(|e| Error::HttpError(e.to_string()))?; + .map_err(|e| { + Error::HttpError( + e.status().map(|status_code| status_code.as_u16()), + e.to_string(), + ) + })?; Ok(Self { core: HttpClientCore { inner: client }, @@ -249,7 +268,13 @@ impl HttpClient { } match result.as_ref() { - Err(Error::Database(_) | Error::HttpError(_) | Error::Custom(_)) => { + Err(Error::HttpError(status_code, _)) => { + let status_code = status_code.to_owned().unwrap_or_default(); + if status_code <= 400 && status_code >= 499 { + // 4xx errors won't be 'solved' by retrying + return result; + } + // retry request, if possible tracing::error!("Failed http_request {:?}", result.as_ref().err());