aws_smithy_runtime_api/client/
behavior_version.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Behavior version of the client
7
8/// Behavior version of the client
9///
10/// Over time, new best-practice behaviors are introduced. However, these behaviors might not be
11/// backwards compatible. For example, a change which introduces new default timeouts or a new
12/// retry-mode for all operations might be the ideal behavior but could break existing applications.
13#[derive(Copy, Clone, PartialEq)]
14pub struct BehaviorVersion {
15    inner: Inner,
16}
17
18#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
19enum Inner {
20    // IMPORTANT: Order matters here for the `Ord` derive. Newer versions go to the bottom.
21    V2023_11_09,
22    V2024_03_28,
23    V2025_01_17,
24    V2025_08_07,
25    V2026_01_12,
26    V2026_05_15,
27}
28
29impl BehaviorVersion {
30    /// This method will always return the latest major version.
31    ///
32    /// This is the recommend choice for customers who aren't reliant on extremely specific behavior
33    /// characteristics. For example, if you are writing a CLI app, the latest behavior major
34    /// version is probably the best setting for you.
35    ///
36    /// If, however, you're writing a service that is very latency sensitive, or that has written
37    /// code to tune Rust SDK behaviors, consider pinning to a specific major version.
38    ///
39    /// The latest version is currently [`BehaviorVersion::v2026_05_15`]
40    pub fn latest() -> Self {
41        Self::v2026_05_15()
42    }
43
44    /// Behavior version for June 1st, 2026.
45    ///
46    /// This version updates retry behavior per the Retry Behavior 2.1 spec:
47    /// - Non-throttling errors use 50ms base backoff (previously 1s)
48    /// - Token bucket costs: 14 for non-throttling, 5 for throttling (previously 5/10)
49    /// - HTTP 5xx status codes no longer trigger connection poisoning
50    /// - `x-amz-retry-after` header bounded between exponential backoff and 5s above it
51    pub fn v2026_05_15() -> Self {
52        Self {
53            inner: Inner::V2026_05_15,
54        }
55    }
56
57    /// Behavior version for January 12th, 2026.
58    ///
59    /// This version enables retries by default for AWS SDK clients. Generic Smithy clients
60    /// (non-AWS) do not have retries enabled by default.
61    ///
62    /// Additionally, this version sets a 3.1 second connect timeout for all clients.
63    ///
64    /// For more information about behavior versions and how they affect SDK behavior, see the
65    /// [AWS SDK for Rust Developer Guide](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/behavior-versions.html).
66    #[deprecated(
67        since = "1.12.1",
68        note = "Superseded by v2026_05_15, which updates retry behavior per the Retry Behavior 2.1 spec."
69    )]
70    pub fn v2026_01_12() -> Self {
71        Self {
72            inner: Inner::V2026_01_12,
73        }
74    }
75
76    /// Behavior version for August 7th, 2025.
77    ///
78    /// This version updates the default HTTPS client to support proxy environment variables
79    /// (e.g. `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`) by default.
80    #[deprecated(
81        since = "1.10.0",
82        note = "Superseded by v2026_01_12, which enables retries by default for AWS SDK clients and sets a 3.1s connect timeout for all clients."
83    )]
84    pub fn v2025_08_07() -> Self {
85        Self {
86            inner: Inner::V2025_08_07,
87        }
88    }
89
90    /// Behavior version for January 17th, 2025
91    ///
92    /// This version updates the default HTTP client and TLS stack. SDKs shipped with
93    /// a pre 1.x version of hyper and rustls originally. This behavior version updates
94    /// the HTTP+TLS stack to maintained versions.
95    ///
96    /// <div class="warning">
97    /// NOTE: In a future release behavior versions prior to this will require enabling
98    /// feature flags manually to keep the legacy Hyper stack as the default. Specifically the
99    /// `aws-smithy-runtime/tls-rustls` feature flag combined with an older behavior version.
100    /// </div>
101    #[deprecated(
102        since = "1.9.0",
103        note = "Superseded by v2025_08_07, which enables automatic HTTP(S) proxy support from environment variables in the default HTTPS client."
104    )]
105    pub fn v2025_01_17() -> Self {
106        Self {
107            inner: Inner::V2025_01_17,
108        }
109    }
110
111    /// Behavior version for March 28th, 2024.
112    ///
113    /// This version enables stalled stream protection for uploads (request bodies) by default.
114    ///
115    /// When a new behavior major version is released, this method will be deprecated.
116    #[deprecated(
117        since = "1.8.0",
118        note = "Superseded by v2025_01_17, which updates the default HTTPS client stack."
119    )]
120    pub fn v2024_03_28() -> Self {
121        Self {
122            inner: Inner::V2024_03_28,
123        }
124    }
125
126    /// Behavior version for November 9th, 2023.
127    #[deprecated(
128        since = "1.4.0",
129        note = "Superseded by v2024_03_28, which enabled stalled stream protection for uploads (request bodies) by default."
130    )]
131    pub fn v2023_11_09() -> Self {
132        Self {
133            inner: Inner::V2023_11_09,
134        }
135    }
136
137    /// True if this version is newer or equal to the given `other` version.
138    pub fn is_at_least(&self, other: BehaviorVersion) -> bool {
139        self.inner >= other.inner
140    }
141}
142
143impl std::fmt::Debug for BehaviorVersion {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        f.debug_tuple("BehaviorVersion").field(&self.inner).finish()
146    }
147}
148
149impl From<BehaviorVersion> for aws_smithy_types::retry::RetrySpec {
150    #[allow(deprecated)]
151    fn from(bv: BehaviorVersion) -> Self {
152        if bv.is_at_least(BehaviorVersion::v2026_05_15()) {
153            Self::v2_1()
154        } else {
155            Self::v2_0()
156        }
157    }
158}
159
160#[cfg(test)]
161mod tests {
162    use super::*;
163
164    #[test]
165    #[allow(deprecated)]
166    fn version_comparison() {
167        assert!(BehaviorVersion::latest() == BehaviorVersion::latest());
168        assert!(BehaviorVersion::v2023_11_09() == BehaviorVersion::v2023_11_09());
169        assert!(BehaviorVersion::v2024_03_28() != BehaviorVersion::v2023_11_09());
170        assert!(BehaviorVersion::v2025_01_17() != BehaviorVersion::v2024_03_28());
171        assert!(BehaviorVersion::latest().is_at_least(BehaviorVersion::latest()));
172        assert!(BehaviorVersion::latest().is_at_least(BehaviorVersion::v2023_11_09()));
173        assert!(BehaviorVersion::latest().is_at_least(BehaviorVersion::v2024_03_28()));
174        assert!(BehaviorVersion::latest().is_at_least(BehaviorVersion::v2025_01_17()));
175        assert!(BehaviorVersion::latest().is_at_least(BehaviorVersion::v2025_08_07()));
176        assert!(BehaviorVersion::latest().is_at_least(BehaviorVersion::v2026_01_12()));
177        assert!(!BehaviorVersion::v2023_11_09().is_at_least(BehaviorVersion::v2024_03_28()));
178        assert!(Inner::V2024_03_28 > Inner::V2023_11_09);
179        assert!(Inner::V2023_11_09 < Inner::V2024_03_28);
180        assert!(Inner::V2024_03_28 < Inner::V2025_01_17);
181        assert!(Inner::V2025_01_17 < Inner::V2025_08_07);
182        assert!(Inner::V2025_08_07 < Inner::V2026_01_12);
183        assert!(Inner::V2026_01_12 < Inner::V2026_05_15);
184    }
185}