stedi_sdk_config/
sdk_config.rs

1#![deny(missing_docs)]
2
3//! Stedi Shared Config
4//!
5//! This module contains an shared configuration representation that is agnostic from a specific service.
6
7use std::sync::Arc;
8
9use aws_smithy_async::rt::sleep::AsyncSleep;
10use aws_smithy_client::http_connector::HttpConnector;
11use aws_smithy_http_auth::api_key::AuthApiKey;
12use aws_smithy_types::retry::RetryConfig;
13use aws_smithy_types::timeout::TimeoutConfig;
14use aws_types::app_name::AppName;
15use aws_types::region::Region;
16
17use crate::endpoint::ResolveStediEndpoint;
18
19/// Stedi Shared Configuration
20#[derive(Debug, Clone)]
21pub struct SdkConfig {
22    app_name: Option<AppName>,
23    api_key: Option<AuthApiKey>,
24    region: Option<Region>,
25    endpoint_resolver: Option<Arc<dyn ResolveStediEndpoint>>,
26    endpoint_url: Option<String>,
27    retry_config: Option<RetryConfig>,
28    sleep_impl: Option<Arc<dyn AsyncSleep>>,
29    timeout_config: Option<TimeoutConfig>,
30    http_connector: Option<HttpConnector>,
31}
32
33/// Builder for Stedi Shared Configuration
34///
35/// _Important:_ Using the `stedi-sdk-config` crate to configure the SDK is preferred to invoking this
36/// builder directly. Using this builder directly won't pull in any Stedi recommended default
37/// configuration values.
38#[derive(Debug, Default)]
39pub struct Builder {
40    app_name: Option<AppName>,
41    api_key: Option<AuthApiKey>,
42    region: Option<Region>,
43    endpoint_resolver: Option<Arc<dyn ResolveStediEndpoint>>,
44    endpoint_url: Option<String>,
45    retry_config: Option<RetryConfig>,
46    sleep_impl: Option<Arc<dyn AsyncSleep>>,
47    timeout_config: Option<TimeoutConfig>,
48    http_connector: Option<HttpConnector>,
49}
50
51impl Builder {
52    /// Set the region for the builder
53    ///
54    /// # Examples
55    /// ```rust
56    /// use stedi_sdk_config::SdkConfig;
57    /// use aws_types::region::Region;
58    /// let config = SdkConfig::builder().region(Region::new("us-east-1")).build();
59    /// ```
60    pub fn region(mut self, region: impl Into<Option<Region>>) -> Self {
61        self.set_region(region);
62        self
63    }
64
65    /// Set the region for the builder
66    ///
67    /// # Examples
68    /// ```rust
69    /// fn region_override() -> Option<Region> {
70    ///     // ...
71    ///     # None
72    /// }
73    /// use stedi_sdk_config::SdkConfig;
74    /// use aws_types::region::Region;
75    /// let mut builder = SdkConfig::builder();
76    /// if let Some(region) = region_override() {
77    ///     builder.set_region(region);
78    /// }
79    /// let config = builder.build();
80    /// ```
81    pub fn set_region(&mut self, region: impl Into<Option<Region>>) -> &mut Self {
82        self.region = region.into();
83        self
84    }
85
86    /// Set the endpoint resolver to use when making requests
87    ///
88    /// This method is deprecated. Use [`Self::endpoint_url`] instead.
89    ///
90    /// # Examples
91    /// ```
92    /// # fn wrapper() -> Result<(), aws_smithy_http::endpoint::error::InvalidEndpointError> {
93    /// use std::sync::Arc;
94    /// use stedi_sdk_config::SdkConfig;
95    /// use aws_smithy_http::endpoint::Endpoint;
96    /// let config = SdkConfig::builder().endpoint_resolver(
97    ///     Endpoint::immutable("http://localhost:8080")?
98    /// ).build();
99    /// # Ok(())
100    /// # }
101    /// ```
102    #[deprecated(note = "use `endpoint_url` instead")]
103    pub fn endpoint_resolver(
104        mut self,
105        endpoint_resolver: impl ResolveStediEndpoint + 'static,
106    ) -> Self {
107        self.set_endpoint_resolver(Some(Arc::new(endpoint_resolver)));
108        self
109    }
110
111    /// Set the endpoint url to use when making requests.
112    /// # Examples
113    /// ```
114    /// use stedi_sdk_config::SdkConfig;
115    /// let config = SdkConfig::builder().endpoint_url("http://localhost:8080").build();
116    /// ```
117    pub fn endpoint_url(mut self, endpoint_url: impl Into<String>) -> Self {
118        self.set_endpoint_url(Some(endpoint_url.into()));
119        self
120    }
121
122    /// Set the endpoint url to use when making requests.
123    pub fn set_endpoint_url(&mut self, endpoint_url: Option<String>) -> &mut Self {
124        self.endpoint_url = endpoint_url;
125        self
126    }
127
128    /// Set the endpoint resolver to use when making requests
129    ///
130    /// # Examples
131    /// ```
132    /// use std::sync::Arc;
133    /// use stedi_sdk_config::SdkConfig;
134    /// use stedi_sdk_config::endpoint::ResolveStediEndpoint;
135    /// fn endpoint_resolver_override() -> Option<Arc<dyn ResolveStediEndpoint>> {
136    ///     // ...
137    ///     # None
138    /// }
139    /// let mut config = SdkConfig::builder();
140    /// config.set_endpoint_resolver(endpoint_resolver_override());
141    /// config.build();
142    /// ```
143    pub fn set_endpoint_resolver(
144        &mut self,
145        endpoint_resolver: Option<Arc<dyn ResolveStediEndpoint>>,
146    ) -> &mut Self {
147        self.endpoint_resolver = endpoint_resolver;
148        self
149    }
150
151    /// Set the retry_config for the builder
152    ///
153    /// _Note:_ Retries require a sleep implementation in order to work. When enabling retry, make
154    /// sure to set one with [Self::sleep_impl] or [Self::set_sleep_impl].
155    ///
156    /// # Examples
157    /// ```rust
158    /// use stedi_sdk_config::SdkConfig;
159    /// use aws_smithy_types::retry::RetryConfig;
160    ///
161    /// let retry_config = RetryConfig::standard().with_max_attempts(5);
162    /// let config = SdkConfig::builder().retry_config(retry_config).build();
163    /// ```
164    pub fn retry_config(mut self, retry_config: RetryConfig) -> Self {
165        self.set_retry_config(Some(retry_config));
166        self
167    }
168
169    /// Set the retry_config for the builder
170    ///
171    /// _Note:_ Retries require a sleep implementation in order to work. When enabling retry, make
172    /// sure to set one with [Self::sleep_impl] or [Self::set_sleep_impl].
173    ///
174    /// # Examples
175    /// ```rust
176    /// use stedi_sdk_config::sdk_config::{SdkConfig, Builder};
177    /// use aws_smithy_types::retry::RetryConfig;
178    ///
179    /// fn disable_retries(builder: &mut Builder) {
180    ///     let retry_config = RetryConfig::standard().with_max_attempts(1);
181    ///     builder.set_retry_config(Some(retry_config));
182    /// }
183    ///
184    /// let mut builder = SdkConfig::builder();
185    /// disable_retries(&mut builder);
186    /// ```
187    pub fn set_retry_config(&mut self, retry_config: Option<RetryConfig>) -> &mut Self {
188        self.retry_config = retry_config;
189        self
190    }
191
192    /// Set the [`TimeoutConfig`] for the builder
193    ///
194    /// _Note:_ Timeouts require a sleep implementation in order to work.
195    /// When enabling timeouts, be sure to set one with [Self::sleep_impl] or
196    /// [Self::set_sleep_impl].
197    ///
198    /// # Examples
199    ///
200    /// ```rust
201    /// # use std::time::Duration;
202    /// use stedi_sdk_config::SdkConfig;
203    /// use aws_smithy_types::timeout::TimeoutConfig;
204    ///
205    /// let timeout_config = TimeoutConfig::builder()
206    ///     .operation_attempt_timeout(Duration::from_secs(2))
207    ///     .operation_timeout(Duration::from_secs(5))
208    ///     .build();
209    /// let config = SdkConfig::builder()
210    ///     .timeout_config(timeout_config)
211    ///     .build();
212    /// ```
213    pub fn timeout_config(mut self, timeout_config: TimeoutConfig) -> Self {
214        self.set_timeout_config(Some(timeout_config));
215        self
216    }
217
218    /// Set the [`TimeoutConfig`] for the builder
219    ///
220    /// _Note:_ Timeouts require a sleep implementation in order to work.
221    /// When enabling timeouts, be sure to set one with [Self::sleep_impl] or
222    /// [Self::set_sleep_impl].
223    ///
224    /// # Examples
225    /// ```rust
226    /// # use std::time::Duration;
227    /// use stedi_sdk_config::sdk_config::{SdkConfig, Builder};
228    /// use aws_smithy_types::timeout::TimeoutConfig;
229    ///
230    /// fn set_preferred_timeouts(builder: &mut Builder) {
231    ///     let timeout_config = TimeoutConfig::builder()
232    ///         .operation_attempt_timeout(Duration::from_secs(2))
233    ///         .operation_timeout(Duration::from_secs(5))
234    ///         .build();
235    ///     builder.set_timeout_config(Some(timeout_config));
236    /// }
237    ///
238    /// let mut builder = SdkConfig::builder();
239    /// set_preferred_timeouts(&mut builder);
240    /// let config = builder.build();
241    /// ```
242    pub fn set_timeout_config(&mut self, timeout_config: Option<TimeoutConfig>) -> &mut Self {
243        self.timeout_config = timeout_config;
244        self
245    }
246
247    /// Set the sleep implementation for the builder. The sleep implementation is used to create
248    /// timeout futures.
249    ///
250    /// _Note:_ If you're using the Tokio runtime, a `TokioSleep` implementation is available in
251    /// the `aws-smithy-async` crate.
252    ///
253    /// # Examples
254    ///
255    /// ```rust
256    /// use std::sync::Arc;
257    /// use aws_smithy_async::rt::sleep::{AsyncSleep, Sleep};
258    /// use stedi_sdk_config::SdkConfig;
259    ///
260    /// ##[derive(Debug)]
261    /// pub struct ForeverSleep;
262    ///
263    /// impl AsyncSleep for ForeverSleep {
264    ///     fn sleep(&self, duration: std::time::Duration) -> Sleep {
265    ///         Sleep::new(std::future::pending())
266    ///     }
267    /// }
268    ///
269    /// let sleep_impl = Arc::new(ForeverSleep);
270    /// let config = SdkConfig::builder().sleep_impl(sleep_impl).build();
271    /// ```
272    pub fn sleep_impl(mut self, sleep_impl: Arc<dyn AsyncSleep>) -> Self {
273        self.set_sleep_impl(Some(sleep_impl));
274        self
275    }
276
277    /// Set the sleep implementation for the builder. The sleep implementation is used to create
278    /// timeout futures.
279    ///
280    /// _Note:_ If you're using the Tokio runtime, a `TokioSleep` implementation is available in
281    /// the `aws-smithy-async` crate.
282    ///
283    /// # Examples
284    /// ```rust
285    /// # use aws_smithy_async::rt::sleep::{AsyncSleep, Sleep};
286    /// # use stedi_sdk_config::sdk_config::{Builder, SdkConfig};
287    /// #[derive(Debug)]
288    /// pub struct ForeverSleep;
289    ///
290    /// impl AsyncSleep for ForeverSleep {
291    ///     fn sleep(&self, duration: std::time::Duration) -> Sleep {
292    ///         Sleep::new(std::future::pending())
293    ///     }
294    /// }
295    ///
296    /// fn set_never_ending_sleep_impl(builder: &mut Builder) {
297    ///     let sleep_impl = std::sync::Arc::new(ForeverSleep);
298    ///     builder.set_sleep_impl(Some(sleep_impl));
299    /// }
300    ///
301    /// let mut builder = SdkConfig::builder();
302    /// set_never_ending_sleep_impl(&mut builder);
303    /// let config = builder.build();
304    /// ```
305    pub fn set_sleep_impl(&mut self, sleep_impl: Option<Arc<dyn AsyncSleep>>) -> &mut Self {
306        self.sleep_impl = sleep_impl;
307        self
308    }
309
310    /// Set the API key for the builder
311    ///
312    /// # Examples
313    /// ```rust
314    /// use aws_smithy_http_auth::api_key::AuthApiKey;
315    /// use stedi_sdk_config::SdkConfig;
316    ///
317    /// let config = SdkConfig::builder()
318    ///     .api_key(AuthApiKey::new("some-api-key"))
319    ///     .build();
320    /// ```
321    pub fn api_key(mut self, api_key: AuthApiKey) -> Self {
322        self.set_api_key(Some(api_key));
323        self
324    }
325
326    /// Set the API key for the builder
327    pub fn set_api_key(&mut self, api_key: Option<AuthApiKey>) -> &mut Self {
328        self.api_key = api_key;
329        self
330    }
331
332    /// Sets the name of the app that is using the client.
333    ///
334    /// This _optional_ name is used to identify the application in the user agent that
335    /// gets sent along with requests.
336    pub fn app_name(mut self, app_name: AppName) -> Self {
337        self.set_app_name(Some(app_name));
338        self
339    }
340
341    /// Sets the name of the app that is using the client.
342    ///
343    /// This _optional_ name is used to identify the application in the user agent that
344    /// gets sent along with requests.
345    pub fn set_app_name(&mut self, app_name: Option<AppName>) -> &mut Self {
346        self.app_name = app_name;
347        self
348    }
349
350    /// Sets the HTTP connector to use when making requests.
351    ///
352    /// ## Examples
353    /// ```no_run
354    /// # #[cfg(feature = "examples")]
355    /// # fn example() {
356    /// use std::time::Duration;
357    /// use aws_smithy_client::{Client, hyper_ext};
358    /// use aws_smithy_client::erase::DynConnector;
359    /// use aws_smithy_client::http_connector::ConnectorSettings;
360    /// use stedi_sdk_config::SdkConfig;
361    ///
362    /// let https_connector = hyper_rustls::HttpsConnectorBuilder::new()
363    ///     .with_webpki_roots()
364    ///     .https_only()
365    ///     .enable_http1()
366    ///     .enable_http2()
367    ///     .build();
368    /// let smithy_connector = hyper_ext::Adapter::builder()
369    ///     // Optionally set things like timeouts as well
370    ///     .connector_settings(
371    ///         ConnectorSettings::builder()
372    ///             .connect_timeout(Duration::from_secs(5))
373    ///             .build()
374    ///     )
375    ///     .build(https_connector);
376    /// let sdk_config = SdkConfig::builder()
377    ///     .http_connector(smithy_connector)
378    ///     .build();
379    /// # }
380    /// ```
381    pub fn http_connector(mut self, http_connector: impl Into<HttpConnector>) -> Self {
382        self.set_http_connector(Some(http_connector));
383        self
384    }
385
386    /// Sets the HTTP connector to use when making requests.
387    ///
388    /// ## Examples
389    /// ```no_run
390    /// # #[cfg(feature = "examples")]
391    /// # fn example() {
392    /// use std::time::Duration;
393    /// use aws_smithy_client::hyper_ext;
394    /// use aws_smithy_client::http_connector::ConnectorSettings;
395    /// use stedi_sdk_config::sdk_config::{SdkConfig, Builder};
396    ///
397    /// fn override_http_connector(builder: &mut Builder) {
398    ///     let https_connector = hyper_rustls::HttpsConnectorBuilder::new()
399    ///         .with_webpki_roots()
400    ///         .https_only()
401    ///         .enable_http1()
402    ///         .enable_http2()
403    ///         .build();
404    ///     let smithy_connector = hyper_ext::Adapter::builder()
405    ///         // Optionally set things like timeouts as well
406    ///         .connector_settings(
407    ///             ConnectorSettings::builder()
408    ///                 .connect_timeout(Duration::from_secs(5))
409    ///                 .build()
410    ///         )
411    ///         .build(https_connector);
412    ///     builder.set_http_connector(Some(smithy_connector));
413    /// }
414    ///
415    /// let mut builder = SdkConfig::builder();
416    /// override_http_connector(&mut builder);
417    /// let config = builder.build();
418    /// # }
419    /// ```
420    pub fn set_http_connector(
421        &mut self,
422        http_connector: Option<impl Into<HttpConnector>>,
423    ) -> &mut Self {
424        self.http_connector = http_connector.map(|inner| inner.into());
425        self
426    }
427
428    /// Build a [`SdkConfig`](SdkConfig) from this builder
429    pub fn build(self) -> SdkConfig {
430        SdkConfig {
431            app_name: self.app_name,
432            api_key: self.api_key,
433            region: self.region,
434            endpoint_resolver: self.endpoint_resolver,
435            endpoint_url: self.endpoint_url,
436            retry_config: self.retry_config,
437            sleep_impl: self.sleep_impl,
438            timeout_config: self.timeout_config,
439            http_connector: self.http_connector,
440        }
441    }
442}
443
444impl SdkConfig {
445    /// Configured region
446    pub fn region(&self) -> Option<&Region> {
447        self.region.as_ref()
448    }
449
450    /// Configured endpoint resolver
451    pub fn endpoint_resolver(&self) -> Option<Arc<dyn ResolveStediEndpoint>> {
452        self.endpoint_resolver.clone()
453    }
454
455    /// Configured endpoint URL
456    pub fn endpoint_url(&self) -> Option<&str> {
457        self.endpoint_url.as_deref()
458    }
459
460    /// Configured retry config
461    pub fn retry_config(&self) -> Option<&RetryConfig> {
462        self.retry_config.as_ref()
463    }
464
465    /// Configured timeout config
466    pub fn timeout_config(&self) -> Option<&TimeoutConfig> {
467        self.timeout_config.as_ref()
468    }
469
470    #[doc(hidden)]
471    /// Configured sleep implementation
472    pub fn sleep_impl(&self) -> Option<Arc<dyn AsyncSleep>> {
473        self.sleep_impl.clone()
474    }
475
476    /// Configured API key
477    pub fn api_key(&self) -> Option<&AuthApiKey> {
478        self.api_key.as_ref()
479    }
480
481    /// Configured app name
482    pub fn app_name(&self) -> Option<&AppName> {
483        self.app_name.as_ref()
484    }
485
486    /// Configured HTTP Connector
487    pub fn http_connector(&self) -> Option<&HttpConnector> {
488        self.http_connector.as_ref()
489    }
490
491    /// Config builder
492    ///
493    /// _Important:_ Using the `stedi-sdk-config` crate to configure the SDK is preferred to invoking this
494    /// builder directly. Using this builder directly won't pull in any Stedi recommended default
495    /// configuration values.
496    pub fn builder() -> Builder {
497        Builder::default()
498    }
499}