aws_sdk_iotmanagedintegrations/config/
endpoint.rs1pub use ::aws_smithy_runtime_api::client::endpoint::EndpointFuture;
3pub use ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver;
4pub use ::aws_smithy_types::endpoint::Endpoint;
5
6#[derive(Debug, Default)]
8pub(crate) struct EndpointOverrideFeatureTrackerInterceptor;
9
10#[::aws_smithy_runtime_api::client::interceptors::dyn_dispatch_hint]
11impl ::aws_smithy_runtime_api::client::interceptors::Intercept for EndpointOverrideFeatureTrackerInterceptor {
12 fn name(&self) -> &'static str {
13 "EndpointOverrideFeatureTrackerInterceptor"
14 }
15
16 fn read_before_execution(
17 &self,
18 _context: &::aws_smithy_runtime_api::client::interceptors::context::BeforeSerializationInterceptorContextRef<'_>,
19 cfg: &mut ::aws_smithy_types::config_bag::ConfigBag,
20 ) -> ::std::result::Result<(), ::aws_smithy_runtime_api::box_error::BoxError> {
21 if cfg.load::<::aws_types::endpoint_config::EndpointUrl>().is_some() {
22 cfg.interceptor_state()
23 .store_append(::aws_runtime::sdk_feature::AwsSdkFeature::EndpointOverride);
24 }
25 ::std::result::Result::Ok(())
26 }
27}
28
29#[cfg(test)]
30mod test {
31
32 #[test]
34 fn test_1() {
35 let params = crate::config::endpoint::Params::builder()
36 .endpoint("https://example.com".to_string())
37 .use_fips(false)
38 .build()
39 .expect("invalid params");
40 let resolver = crate::config::endpoint::DefaultResolver::new();
41 let endpoint = resolver.resolve_endpoint(¶ms);
42 let endpoint = endpoint.expect("Expected valid endpoint: https://example.com");
43 assert_eq!(
44 endpoint,
45 ::aws_smithy_types::endpoint::Endpoint::builder().url("https://example.com").build()
46 );
47 }
48
49 #[test]
51 fn test_2() {
52 let params = crate::config::endpoint::Params::builder()
53 .endpoint("https://example.com".to_string())
54 .use_fips(true)
55 .build()
56 .expect("invalid params");
57 let resolver = crate::config::endpoint::DefaultResolver::new();
58 let endpoint = resolver.resolve_endpoint(¶ms);
59 let error = endpoint
60 .expect_err("expected error: Invalid Configuration: FIPS and custom endpoint are not supported [For custom endpoint with fips enabled]");
61 assert_eq!(format!("{}", error), "Invalid Configuration: FIPS and custom endpoint are not supported")
62 }
63
64 #[test]
66 fn test_3() {
67 let params = crate::config::endpoint::Params::builder()
68 .region("us-east-1".to_string())
69 .use_fips(true)
70 .build()
71 .expect("invalid params");
72 let resolver = crate::config::endpoint::DefaultResolver::new();
73 let endpoint = resolver.resolve_endpoint(¶ms);
74 let endpoint = endpoint.expect("Expected valid endpoint: https://api.iotmanagedintegrations-fips.us-east-1.api.aws");
75 assert_eq!(
76 endpoint,
77 ::aws_smithy_types::endpoint::Endpoint::builder()
78 .url("https://api.iotmanagedintegrations-fips.us-east-1.api.aws")
79 .build()
80 );
81 }
82
83 #[test]
85 fn test_4() {
86 let params = crate::config::endpoint::Params::builder()
87 .region("us-east-1".to_string())
88 .use_fips(false)
89 .build()
90 .expect("invalid params");
91 let resolver = crate::config::endpoint::DefaultResolver::new();
92 let endpoint = resolver.resolve_endpoint(¶ms);
93 let endpoint = endpoint.expect("Expected valid endpoint: https://api.iotmanagedintegrations.us-east-1.api.aws");
94 assert_eq!(
95 endpoint,
96 ::aws_smithy_types::endpoint::Endpoint::builder()
97 .url("https://api.iotmanagedintegrations.us-east-1.api.aws")
98 .build()
99 );
100 }
101
102 #[test]
104 fn test_5() {
105 let params = crate::config::endpoint::Params::builder()
106 .region("cn-northwest-1".to_string())
107 .use_fips(true)
108 .build()
109 .expect("invalid params");
110 let resolver = crate::config::endpoint::DefaultResolver::new();
111 let endpoint = resolver.resolve_endpoint(¶ms);
112 let endpoint =
113 endpoint.expect("Expected valid endpoint: https://api.iotmanagedintegrations-fips.cn-northwest-1.api.amazonwebservices.com.cn");
114 assert_eq!(
115 endpoint,
116 ::aws_smithy_types::endpoint::Endpoint::builder()
117 .url("https://api.iotmanagedintegrations-fips.cn-northwest-1.api.amazonwebservices.com.cn")
118 .build()
119 );
120 }
121
122 #[test]
124 fn test_6() {
125 let params = crate::config::endpoint::Params::builder()
126 .region("cn-northwest-1".to_string())
127 .use_fips(false)
128 .build()
129 .expect("invalid params");
130 let resolver = crate::config::endpoint::DefaultResolver::new();
131 let endpoint = resolver.resolve_endpoint(¶ms);
132 let endpoint = endpoint.expect("Expected valid endpoint: https://api.iotmanagedintegrations.cn-northwest-1.api.amazonwebservices.com.cn");
133 assert_eq!(
134 endpoint,
135 ::aws_smithy_types::endpoint::Endpoint::builder()
136 .url("https://api.iotmanagedintegrations.cn-northwest-1.api.amazonwebservices.com.cn")
137 .build()
138 );
139 }
140
141 #[test]
143 fn test_7() {
144 let params = crate::config::endpoint::Params::builder()
145 .region("us-gov-west-1".to_string())
146 .use_fips(true)
147 .build()
148 .expect("invalid params");
149 let resolver = crate::config::endpoint::DefaultResolver::new();
150 let endpoint = resolver.resolve_endpoint(¶ms);
151 let endpoint = endpoint.expect("Expected valid endpoint: https://api.iotmanagedintegrations-fips.us-gov-west-1.api.aws");
152 assert_eq!(
153 endpoint,
154 ::aws_smithy_types::endpoint::Endpoint::builder()
155 .url("https://api.iotmanagedintegrations-fips.us-gov-west-1.api.aws")
156 .build()
157 );
158 }
159
160 #[test]
162 fn test_8() {
163 let params = crate::config::endpoint::Params::builder()
164 .region("us-gov-west-1".to_string())
165 .use_fips(false)
166 .build()
167 .expect("invalid params");
168 let resolver = crate::config::endpoint::DefaultResolver::new();
169 let endpoint = resolver.resolve_endpoint(¶ms);
170 let endpoint = endpoint.expect("Expected valid endpoint: https://api.iotmanagedintegrations.us-gov-west-1.api.aws");
171 assert_eq!(
172 endpoint,
173 ::aws_smithy_types::endpoint::Endpoint::builder()
174 .url("https://api.iotmanagedintegrations.us-gov-west-1.api.aws")
175 .build()
176 );
177 }
178
179 #[test]
181 fn test_9() {
182 let params = crate::config::endpoint::Params::builder().build().expect("invalid params");
183 let resolver = crate::config::endpoint::DefaultResolver::new();
184 let endpoint = resolver.resolve_endpoint(¶ms);
185 let error = endpoint.expect_err("expected error: Invalid Configuration: Missing Region [Missing region]");
186 assert_eq!(format!("{}", error), "Invalid Configuration: Missing Region")
187 }
188}
189
190pub trait ResolveEndpoint: ::std::marker::Send + ::std::marker::Sync + ::std::fmt::Debug {
192 fn resolve_endpoint<'a>(&'a self, params: &'a crate::config::endpoint::Params) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a>;
194
195 fn into_shared_resolver(self) -> ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver
199 where
200 Self: Sized + 'static,
201 {
202 ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver::new(DowncastParams(self))
203 }
204}
205
206#[derive(Debug)]
207struct DowncastParams<T>(T);
208impl<T> ::aws_smithy_runtime_api::client::endpoint::ResolveEndpoint for DowncastParams<T>
209where
210 T: ResolveEndpoint,
211{
212 fn resolve_endpoint<'a>(
213 &'a self,
214 params: &'a ::aws_smithy_runtime_api::client::endpoint::EndpointResolverParams,
215 ) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a> {
216 let ep = match params.get::<crate::config::endpoint::Params>() {
217 Some(params) => self.0.resolve_endpoint(params),
218 None => ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(Err("params of expected type was not present".into())),
219 };
220 ep
221 }
222}
223
224#[derive(Debug)]
225pub struct DefaultResolver {
227 partition_resolver: &'static crate::endpoint_lib::partition::PartitionResolver,
228 endpoint_cache: ::arc_swap::ArcSwap<::std::option::Option<(Params, ::aws_smithy_types::endpoint::Endpoint)>>,
229}
230
231impl Default for DefaultResolver {
232 fn default() -> Self {
233 Self::new()
234 }
235}
236
237impl DefaultResolver {
238 pub fn new() -> Self {
240 Self {
241 partition_resolver: &crate::endpoint_lib::DEFAULT_PARTITION_RESOLVER,
242 endpoint_cache: ::arc_swap::ArcSwap::from_pointee(None),
243 }
244 }
245
246 #[allow(
247 unused_variables,
248 unused_parens,
249 clippy::double_parens,
250 clippy::useless_conversion,
251 clippy::bool_comparison,
252 clippy::comparison_to_empty,
253 clippy::needless_borrow,
254 clippy::useless_asref,
255 clippy::redundant_closure_call,
256 clippy::clone_on_copy,
257 clippy::single_char_add_str
258 )]
259 fn resolve_endpoint<'a>(
260 &'a self,
261 params: &'a crate::config::endpoint::Params,
262 ) -> ::std::result::Result<::aws_smithy_types::endpoint::Endpoint, ::aws_smithy_runtime_api::box_error::BoxError> {
263 let mut _diagnostic_collector = crate::endpoint_lib::diagnostic::DiagnosticCollector::new();
264 #[allow(unused_mut)]
265 let mut context = ConditionContext::default();
266
267 let use_fips = ¶ms.use_fips;
269 let endpoint = ¶ms.endpoint;
270 let region = ¶ms.region;
271
272 let mut current_ref: i32 = 2;
273 loop {
274 match current_ref {
275 ref_val if ref_val >= 100_000_000 => {
276 return match (ref_val - 100_000_000) as usize {
277 0 => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
278 "No endpoint rule matched",
279 )) as ::aws_smithy_runtime_api::box_error::BoxError),
280 1 => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
281 "Invalid Configuration: FIPS and custom endpoint are not supported".to_string(),
282 )) as ::aws_smithy_runtime_api::box_error::BoxError),
283 2 => {
284 let endpoint = params.endpoint.as_deref().unwrap_or_default();
285 ::std::result::Result::Ok(::aws_smithy_types::endpoint::Endpoint::builder().url(endpoint.to_owned()).build())
286 }
287 3 => {
288 let region = params.region.as_deref().unwrap_or_default();
289 let partition_result = context.partition_result.as_ref().expect("Guaranteed to have a value by earlier checks.");
290 ::std::result::Result::Ok(
291 ::aws_smithy_types::endpoint::Endpoint::builder()
292 .url({
293 let mut out = String::new();
294 out.push_str("https://api.iotmanagedintegrations-fips.");
295 #[allow(clippy::needless_borrow)]
296 out.push_str(®ion.as_ref());
297 out.push_str(".");
298 #[allow(clippy::needless_borrow)]
299 out.push_str(&partition_result.dual_stack_dns_suffix());
300 out
301 })
302 .build(),
303 )
304 }
305 4 => {
306 let region = params.region.as_deref().unwrap_or_default();
307 let partition_result = context.partition_result.as_ref().expect("Guaranteed to have a value by earlier checks.");
308 ::std::result::Result::Ok(
309 ::aws_smithy_types::endpoint::Endpoint::builder()
310 .url({
311 let mut out = String::new();
312 out.push_str("https://api.iotmanagedintegrations.");
313 #[allow(clippy::needless_borrow)]
314 out.push_str(®ion.as_ref());
315 out.push_str(".");
316 #[allow(clippy::needless_borrow)]
317 out.push_str(&partition_result.dual_stack_dns_suffix());
318 out
319 })
320 .build(),
321 )
322 }
323 5 => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
324 "Invalid Configuration: Missing Region".to_string(),
325 )) as ::aws_smithy_runtime_api::box_error::BoxError),
326 _ => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
327 "No endpoint rule matched",
328 )) as ::aws_smithy_runtime_api::box_error::BoxError),
329 };
330 }
331 1 | -1 => {
332 return ::std::result::Result::Err(
333 Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message("No endpoint rule matched"))
334 as ::aws_smithy_runtime_api::box_error::BoxError,
335 )
336 }
337 ref_val => {
338 let is_complement = ref_val < 0;
339 let node = &NODES[(ref_val.unsigned_abs() as usize) - 1];
340 let condition_result = match node.condition_index {
341 0 => endpoint.is_some(),
342 1 => region.is_some(),
343 2 => (|_diagnostic_collector: &mut crate::endpoint_lib::diagnostic::DiagnosticCollector| -> bool {
344 let partition_result = &mut context.partition_result;
345 let partition_resolver = &self.partition_resolver;
346 {
347 *partition_result = partition_resolver
348 .resolve_partition(if let Some(param) = region { param } else { return false }, _diagnostic_collector)
349 .map(|inner| inner.into());
350 partition_result.is_some()
351 }
352 })(&mut _diagnostic_collector),
353 3 => (use_fips) == (&true),
354 _ => unreachable!("Invalid condition index"),
355 };
356 current_ref = if is_complement ^ condition_result { node.high_ref } else { node.low_ref };
357 }
358 }
359 }
360 }
361}
362
363impl crate::config::endpoint::ResolveEndpoint for DefaultResolver {
364 fn resolve_endpoint<'a>(&'a self, params: &'a crate::config::endpoint::Params) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a> {
365 let cached = self.endpoint_cache.load();
367 if let Some((cached_params, cached_endpoint)) = cached.as_ref() {
368 if cached_params == params {
369 return ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(::std::result::Result::Ok(cached_endpoint.clone()));
370 }
371 }
372 drop(cached);
373 let result = self.resolve_endpoint(params);
374 if let ::std::result::Result::Ok(ref endpoint) = result {
375 self.endpoint_cache.store(::std::sync::Arc::new(Some((params.clone(), endpoint.clone()))));
376 }
377 ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(result)
378 }
379}
380const NODES: [crate::endpoint_lib::bdd_interpreter::BddNode; 6] = [
381 crate::endpoint_lib::bdd_interpreter::BddNode {
382 condition_index: -1,
383 high_ref: 1,
384 low_ref: -1,
385 },
386 crate::endpoint_lib::bdd_interpreter::BddNode {
387 condition_index: 0,
388 high_ref: 6,
389 low_ref: 3,
390 },
391 crate::endpoint_lib::bdd_interpreter::BddNode {
392 condition_index: 1,
393 high_ref: 4,
394 low_ref: 100000005,
395 },
396 crate::endpoint_lib::bdd_interpreter::BddNode {
397 condition_index: 2,
398 high_ref: 5,
399 low_ref: 100000005,
400 },
401 crate::endpoint_lib::bdd_interpreter::BddNode {
402 condition_index: 3,
403 high_ref: 100000003,
404 low_ref: 100000004,
405 },
406 crate::endpoint_lib::bdd_interpreter::BddNode {
407 condition_index: 3,
408 high_ref: 100000001,
409 low_ref: 100000002,
410 },
411];
412#[derive(Default)]
415#[allow(unused_lifetimes)]
416pub(crate) struct ConditionContext<'a> {
417 pub(crate) partition_result: Option<crate::endpoint_lib::partition::Partition<'a>>,
418 phantom: std::marker::PhantomData<&'a ()>,
420}
421
422#[non_exhaustive]
423#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::fmt::Debug)]
424pub struct Params {
426 pub(crate) use_fips: bool,
428 pub(crate) endpoint: ::std::option::Option<::std::string::String>,
430 pub(crate) region: ::std::option::Option<::std::string::String>,
432}
433impl Params {
434 pub fn builder() -> crate::config::endpoint::ParamsBuilder {
436 crate::config::endpoint::ParamsBuilder::default()
437 }
438 pub fn use_fips(&self) -> ::std::option::Option<bool> {
440 Some(self.use_fips)
441 }
442 pub fn endpoint(&self) -> ::std::option::Option<&str> {
444 self.endpoint.as_deref()
445 }
446 pub fn region(&self) -> ::std::option::Option<&str> {
448 self.region.as_deref()
449 }
450}
451
452#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::default::Default, ::std::fmt::Debug)]
454pub struct ParamsBuilder {
455 use_fips: ::std::option::Option<bool>,
456 endpoint: ::std::option::Option<::std::string::String>,
457 region: ::std::option::Option<::std::string::String>,
458}
459impl ParamsBuilder {
460 pub fn build(self) -> ::std::result::Result<crate::config::endpoint::Params, crate::config::endpoint::InvalidParams> {
462 if let Some(region) = &self.region {
463 if !crate::endpoint_lib::host::is_valid_host_label(
464 region.as_ref() as &str,
465 true,
466 &mut crate::endpoint_lib::diagnostic::DiagnosticCollector::new(),
467 ) {
468 return Err(crate::config::endpoint::InvalidParams::invalid_value(
469 "region",
470 "must be a valid host label",
471 ));
472 }
473 };
474 Ok(
475 #[allow(clippy::unnecessary_lazy_evaluations)]
476 crate::config::endpoint::Params {
477 use_fips: self
478 .use_fips
479 .or_else(|| Some(false))
480 .ok_or_else(|| crate::config::endpoint::InvalidParams::missing("use_fips"))?,
481 endpoint: self.endpoint,
482 region: self.region,
483 },
484 )
485 }
486 pub fn use_fips(mut self, value: impl Into<bool>) -> Self {
491 self.use_fips = Some(value.into());
492 self
493 }
494
495 pub fn set_use_fips(mut self, param: Option<bool>) -> Self {
500 self.use_fips = param;
501 self
502 }
503 pub fn endpoint(mut self, value: impl Into<::std::string::String>) -> Self {
507 self.endpoint = Some(value.into());
508 self
509 }
510
511 pub fn set_endpoint(mut self, param: Option<::std::string::String>) -> Self {
515 self.endpoint = param;
516 self
517 }
518 pub fn region(mut self, value: impl Into<::std::string::String>) -> Self {
522 self.region = Some(value.into());
523 self
524 }
525
526 pub fn set_region(mut self, param: Option<::std::string::String>) -> Self {
530 self.region = param;
531 self
532 }
533}
534
535#[derive(Debug)]
537pub struct InvalidParams {
538 field: std::borrow::Cow<'static, str>,
539 kind: InvalidParamsErrorKind,
540}
541
542#[derive(Debug)]
544enum InvalidParamsErrorKind {
545 MissingField,
546 InvalidValue { message: &'static str },
547}
548
549impl InvalidParams {
550 #[allow(dead_code)]
551 fn missing(field: &'static str) -> Self {
552 Self {
553 field: field.into(),
554 kind: InvalidParamsErrorKind::MissingField,
555 }
556 }
557
558 #[allow(dead_code)]
559 fn invalid_value(field: &'static str, message: &'static str) -> Self {
560 Self {
561 field: field.into(),
562 kind: InvalidParamsErrorKind::InvalidValue { message },
563 }
564 }
565}
566
567impl std::fmt::Display for InvalidParams {
568 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
569 match self.kind {
570 InvalidParamsErrorKind::MissingField => write!(f, "a required field was missing: `{}`", self.field),
571 InvalidParamsErrorKind::InvalidValue { message } => write!(f, "invalid value for field: `{}` - {}", self.field, message),
572 }
573 }
574}
575
576impl std::error::Error for InvalidParams {}