diff --git a/reqwest-retry/Cargo.toml b/reqwest-retry/Cargo.toml index 9afded0f..22ebe4dc 100644 --- a/reqwest-retry/Cargo.toml +++ b/reqwest-retry/Cargo.toml @@ -21,7 +21,7 @@ async-trait = "0.1.51" futures = "0.3.0" http = "1.0" reqwest = { version = "0.13.1", default-features = false } -retry-policies = "0.5" +retry-policies = { git = "https://github.com/andyolivares/retry-policies.git", branch = "retry_policy_with_extras" } thiserror = "2.0" tracing = { version = "0.1.26", optional = true } diff --git a/reqwest-retry/src/middleware.rs b/reqwest-retry/src/middleware.rs index a8339c1c..5e0f16c6 100644 --- a/reqwest-retry/src/middleware.rs +++ b/reqwest-retry/src/middleware.rs @@ -1,4 +1,6 @@ //! `RetryTransientMiddleware` implements retrying requests on transient errors. +use std::collections::HashMap; +use std::hash::Hash; use std::time::{Duration, SystemTime}; use crate::retryable_strategy::RetryableStrategy; @@ -161,7 +163,9 @@ where if let Some(Retryable::Transient) = self.retryable_strategy.handle(&result) { // If the response failed and the error type was transient // we can safely try to retry the request. - let retry_decision = self.retry_policy.should_retry(start_time, n_past_retries); + let res = result.as_ref().ok(); + let extras = get_extras(&req, res); + let retry_decision = self.retry_policy.should_retry(start_time, n_past_retries, Some(extras)); if let retry_policies::RetryDecision::Retry { execute_after } = retry_decision { let duration = execute_after .duration_since(SystemTime::now()) @@ -201,3 +205,38 @@ where } } } + +fn get_request_extras(request: &reqwest::Request) -> HashMap { + let mut extras = HashMap::new(); + + extras.insert("request:method".to_string(), request.method().to_string()); + extras.insert("request:url".to_string(), request.url().to_string()); + + for (name, value) in request.headers().iter() { + extras.insert(format!("request:headers:{}", name), value.to_str().unwrap_or("").to_string().to_lowercase()); + } + + extras +} + +fn get_response_extras(response: &reqwest::Response) -> HashMap { + let mut extras = HashMap::new(); + + extras.insert("response:status".to_string(), response.status().to_string()); + + for (name, value) in response.headers().iter() { + extras.insert(format!("response:headers:{}", name), value.to_str().unwrap_or("").to_string().to_lowercase()); + } + + extras +} + +fn get_extras(request: &reqwest::Request, response: Option<&reqwest::Response>) -> HashMap { + let mut extras = get_request_extras(request); + + if let Some(resp) = response { + extras.extend(get_response_extras(resp)); + } + + extras +} \ No newline at end of file