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 std::str::FromStr;
11
12use http::Method;
13use parse_display::FromStr as DeriveFromStr;
14use serde::{Deserialize, Serialize};
15
16use super::HttpConfigError;
17
18/// HTTP method policy used to decide whether a request can be retried.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, DeriveFromStr)]
20#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
21pub enum HttpRetryMethodPolicy {
22    /// Retry only HTTP methods that are safe to replay by default.
23    #[default]
24    #[display("IDEMPOTENT_ONLY")]
25    #[from_str(regex = "(?i)IDEMPOTENT_ONLY|IDEMPOTENT")]
26    IdempotentOnly,
27    /// Retry all HTTP methods, including `POST` and `PATCH`.
28    #[display("ALL_METHODS")]
29    #[from_str(regex = "(?i)ALL_METHODS|ALL")]
30    AllMethods,
31    /// Disable method-level retry eligibility.
32    #[display("NONE")]
33    #[from_str(regex = "(?i)NONE|DISABLED")]
34    None,
35}
36
37impl HttpRetryMethodPolicy {
38    pub(super) fn from_config_value(value: &str) -> Result<Self, HttpConfigError> {
39        Self::from_str(value.trim()).map_err(|_| {
40            HttpConfigError::invalid_value(
41                "method_policy",
42                format!("Unsupported retry method policy: {value}"),
43            )
44        })
45    }
46
47    /// Returns whether the retry executor permits replaying `method`.
48    ///
49    /// # Parameters
50    /// - `method`: HTTP method to evaluate.
51    ///
52    /// # Returns
53    /// `true` when automatic retry may replay the method.
54    pub fn allows_method(&self, method: &Method) -> bool {
55        match self {
56            Self::IdempotentOnly => matches!(
57                *method,
58                Method::GET
59                    | Method::HEAD
60                    | Method::PUT
61                    | Method::DELETE
62                    | Method::OPTIONS
63                    | Method::TRACE
64            ),
65            Self::AllMethods => true,
66            Self::None => false,
67        }
68    }
69}