Skip to main content

qubit_http/options/
http_retry_method_policy.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9
10use http::Method;
11
12use super::HttpConfigError;
13
14/// HTTP method policy used to decide whether a request can be retried.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
16pub enum HttpRetryMethodPolicy {
17    /// Retry only HTTP methods that are safe to replay by default.
18    #[default]
19    IdempotentOnly,
20    /// Retry all HTTP methods, including `POST` and `PATCH`.
21    AllMethods,
22    /// Disable method-level retry eligibility.
23    None,
24}
25
26impl HttpRetryMethodPolicy {
27    pub(super) fn from_config_value(value: &str) -> Result<Self, HttpConfigError> {
28        let normalized = value.trim().to_ascii_uppercase().replace('-', "_");
29        match normalized.as_str() {
30            "IDEMPOTENT_ONLY" | "IDEMPOTENT" => Ok(Self::IdempotentOnly),
31            "ALL_METHODS" | "ALL" => Ok(Self::AllMethods),
32            "NONE" | "DISABLED" => Ok(Self::None),
33            _ => Err(HttpConfigError::invalid_value(
34                "method_policy",
35                format!("Unsupported retry method policy: {value}"),
36            )),
37        }
38    }
39
40    /// Returns whether the retry executor permits replaying `method`.
41    ///
42    /// # Parameters
43    /// - `method`: HTTP method to evaluate.
44    ///
45    /// # Returns
46    /// `true` when automatic retry may replay the method.
47    pub fn allows_method(&self, method: &Method) -> bool {
48        match self {
49            Self::IdempotentOnly => matches!(
50                *method,
51                Method::GET
52                    | Method::HEAD
53                    | Method::PUT
54                    | Method::DELETE
55                    | Method::OPTIONS
56                    | Method::TRACE
57            ),
58            Self::AllMethods => true,
59            Self::None => false,
60        }
61    }
62}