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}