aws_sdk_securityagent/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://securityagent-fips.us-east-1.api.aws");
75 assert_eq!(
76 endpoint,
77 ::aws_smithy_types::endpoint::Endpoint::builder()
78 .url("https://securityagent-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://securityagent.us-east-1.api.aws");
94 assert_eq!(
95 endpoint,
96 ::aws_smithy_types::endpoint::Endpoint::builder()
97 .url("https://securityagent.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 = endpoint.expect("Expected valid endpoint: https://securityagent-fips.cn-northwest-1.api.amazonwebservices.com.cn");
113 assert_eq!(
114 endpoint,
115 ::aws_smithy_types::endpoint::Endpoint::builder()
116 .url("https://securityagent-fips.cn-northwest-1.api.amazonwebservices.com.cn")
117 .build()
118 );
119 }
120
121 #[test]
123 fn test_6() {
124 let params = crate::config::endpoint::Params::builder()
125 .region("cn-northwest-1".to_string())
126 .use_fips(false)
127 .build()
128 .expect("invalid params");
129 let resolver = crate::config::endpoint::DefaultResolver::new();
130 let endpoint = resolver.resolve_endpoint(¶ms);
131 let endpoint = endpoint.expect("Expected valid endpoint: https://securityagent.cn-northwest-1.api.amazonwebservices.com.cn");
132 assert_eq!(
133 endpoint,
134 ::aws_smithy_types::endpoint::Endpoint::builder()
135 .url("https://securityagent.cn-northwest-1.api.amazonwebservices.com.cn")
136 .build()
137 );
138 }
139
140 #[test]
142 fn test_7() {
143 let params = crate::config::endpoint::Params::builder()
144 .region("us-gov-west-1".to_string())
145 .use_fips(true)
146 .build()
147 .expect("invalid params");
148 let resolver = crate::config::endpoint::DefaultResolver::new();
149 let endpoint = resolver.resolve_endpoint(¶ms);
150 let endpoint = endpoint.expect("Expected valid endpoint: https://securityagent-fips.us-gov-west-1.api.aws");
151 assert_eq!(
152 endpoint,
153 ::aws_smithy_types::endpoint::Endpoint::builder()
154 .url("https://securityagent-fips.us-gov-west-1.api.aws")
155 .build()
156 );
157 }
158
159 #[test]
161 fn test_8() {
162 let params = crate::config::endpoint::Params::builder()
163 .region("us-gov-west-1".to_string())
164 .use_fips(false)
165 .build()
166 .expect("invalid params");
167 let resolver = crate::config::endpoint::DefaultResolver::new();
168 let endpoint = resolver.resolve_endpoint(¶ms);
169 let endpoint = endpoint.expect("Expected valid endpoint: https://securityagent.us-gov-west-1.api.aws");
170 assert_eq!(
171 endpoint,
172 ::aws_smithy_types::endpoint::Endpoint::builder()
173 .url("https://securityagent.us-gov-west-1.api.aws")
174 .build()
175 );
176 }
177
178 #[test]
180 fn test_9() {
181 let params = crate::config::endpoint::Params::builder().build().expect("invalid params");
182 let resolver = crate::config::endpoint::DefaultResolver::new();
183 let endpoint = resolver.resolve_endpoint(¶ms);
184 let error = endpoint.expect_err("expected error: Invalid Configuration: Missing Region [Missing region]");
185 assert_eq!(format!("{}", error), "Invalid Configuration: Missing Region")
186 }
187}
188
189pub trait ResolveEndpoint: ::std::marker::Send + ::std::marker::Sync + ::std::fmt::Debug {
191 fn resolve_endpoint<'a>(&'a self, params: &'a crate::config::endpoint::Params) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a>;
193
194 fn into_shared_resolver(self) -> ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver
198 where
199 Self: Sized + 'static,
200 {
201 ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver::new(DowncastParams(self))
202 }
203}
204
205#[derive(Debug)]
206struct DowncastParams<T>(T);
207impl<T> ::aws_smithy_runtime_api::client::endpoint::ResolveEndpoint for DowncastParams<T>
208where
209 T: ResolveEndpoint,
210{
211 fn resolve_endpoint<'a>(
212 &'a self,
213 params: &'a ::aws_smithy_runtime_api::client::endpoint::EndpointResolverParams,
214 ) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a> {
215 let ep = match params.get::<crate::config::endpoint::Params>() {
216 Some(params) => self.0.resolve_endpoint(params),
217 None => ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(Err("params of expected type was not present".into())),
218 };
219 ep
220 }
221}
222
223#[derive(Debug)]
224pub struct DefaultResolver {
226 partition_resolver: &'static crate::endpoint_lib::partition::PartitionResolver,
227 endpoint_cache: ::arc_swap::ArcSwap<::std::option::Option<(Params, ::aws_smithy_types::endpoint::Endpoint)>>,
228}
229
230impl Default for DefaultResolver {
231 fn default() -> Self {
232 Self::new()
233 }
234}
235
236impl DefaultResolver {
237 pub fn new() -> Self {
239 Self {
240 partition_resolver: &crate::endpoint_lib::DEFAULT_PARTITION_RESOLVER,
241 endpoint_cache: ::arc_swap::ArcSwap::from_pointee(None),
242 }
243 }
244
245 #[allow(
246 unused_variables,
247 unused_parens,
248 clippy::double_parens,
249 clippy::useless_conversion,
250 clippy::bool_comparison,
251 clippy::comparison_to_empty,
252 clippy::needless_borrow,
253 clippy::useless_asref,
254 clippy::redundant_closure_call,
255 clippy::clone_on_copy,
256 clippy::single_char_add_str
257 )]
258 fn resolve_endpoint<'a>(
259 &'a self,
260 params: &'a crate::config::endpoint::Params,
261 ) -> ::std::result::Result<::aws_smithy_types::endpoint::Endpoint, ::aws_smithy_runtime_api::box_error::BoxError> {
262 let mut _diagnostic_collector = crate::endpoint_lib::diagnostic::DiagnosticCollector::new();
263 #[allow(unused_mut)]
264 let mut context = ConditionContext::default();
265
266 let use_fips = ¶ms.use_fips;
268 let endpoint = ¶ms.endpoint;
269 let region = ¶ms.region;
270
271 let mut current_ref: i32 = 2;
272 loop {
273 match current_ref {
274 ref_val if ref_val >= 100_000_000 => {
275 return match (ref_val - 100_000_000) as usize {
276 0 => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
277 "No endpoint rule matched",
278 )) as ::aws_smithy_runtime_api::box_error::BoxError),
279 1 => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
280 "Invalid Configuration: FIPS and custom endpoint are not supported".to_string(),
281 )) as ::aws_smithy_runtime_api::box_error::BoxError),
282 2 => {
283 let endpoint = params.endpoint.as_deref().unwrap_or_default();
284 ::std::result::Result::Ok(::aws_smithy_types::endpoint::Endpoint::builder().url(endpoint.to_owned()).build())
285 }
286 3 => {
287 let region = params.region.as_deref().unwrap_or_default();
288 let partition_result = context.partition_result.as_ref().expect("Guaranteed to have a value by earlier checks.");
289 ::std::result::Result::Ok(
290 ::aws_smithy_types::endpoint::Endpoint::builder()
291 .url({
292 let mut out = String::new();
293 out.push_str("https://securityagent-fips.");
294 #[allow(clippy::needless_borrow)]
295 out.push_str(®ion.as_ref());
296 out.push_str(".");
297 #[allow(clippy::needless_borrow)]
298 out.push_str(&partition_result.dual_stack_dns_suffix());
299 out
300 })
301 .build(),
302 )
303 }
304 4 => {
305 let region = params.region.as_deref().unwrap_or_default();
306 let partition_result = context.partition_result.as_ref().expect("Guaranteed to have a value by earlier checks.");
307 ::std::result::Result::Ok(
308 ::aws_smithy_types::endpoint::Endpoint::builder()
309 .url({
310 let mut out = String::new();
311 out.push_str("https://securityagent.");
312 #[allow(clippy::needless_borrow)]
313 out.push_str(®ion.as_ref());
314 out.push_str(".");
315 #[allow(clippy::needless_borrow)]
316 out.push_str(&partition_result.dual_stack_dns_suffix());
317 out
318 })
319 .build(),
320 )
321 }
322 5 => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
323 "Invalid Configuration: Missing Region".to_string(),
324 )) as ::aws_smithy_runtime_api::box_error::BoxError),
325 _ => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message(
326 "No endpoint rule matched",
327 )) as ::aws_smithy_runtime_api::box_error::BoxError),
328 };
329 }
330 1 | -1 => {
331 return ::std::result::Result::Err(
332 Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message("No endpoint rule matched"))
333 as ::aws_smithy_runtime_api::box_error::BoxError,
334 )
335 }
336 ref_val => {
337 let is_complement = ref_val < 0;
338 let node = &NODES[(ref_val.unsigned_abs() as usize) - 1];
339 let condition_result = match node.condition_index {
340 0 => endpoint.is_some(),
341 1 => region.is_some(),
342 2 => (|_diagnostic_collector: &mut crate::endpoint_lib::diagnostic::DiagnosticCollector| -> bool {
343 let partition_result = &mut context.partition_result;
344 let partition_resolver = &self.partition_resolver;
345 {
346 *partition_result = partition_resolver
347 .resolve_partition(if let Some(param) = region { param } else { return false }, _diagnostic_collector)
348 .map(|inner| inner.into());
349 partition_result.is_some()
350 }
351 })(&mut _diagnostic_collector),
352 3 => (use_fips) == (&true),
353 _ => unreachable!("Invalid condition index"),
354 };
355 current_ref = if is_complement ^ condition_result { node.high_ref } else { node.low_ref };
356 }
357 }
358 }
359 }
360}
361
362impl crate::config::endpoint::ResolveEndpoint for DefaultResolver {
363 fn resolve_endpoint<'a>(&'a self, params: &'a crate::config::endpoint::Params) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a> {
364 let cached = self.endpoint_cache.load();
366 if let Some((cached_params, cached_endpoint)) = cached.as_ref() {
367 if cached_params == params {
368 return ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(::std::result::Result::Ok(cached_endpoint.clone()));
369 }
370 }
371 drop(cached);
372 let result = self.resolve_endpoint(params);
373 if let ::std::result::Result::Ok(ref endpoint) = result {
374 self.endpoint_cache.store(::std::sync::Arc::new(Some((params.clone(), endpoint.clone()))));
375 }
376 ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(result)
377 }
378}
379const NODES: [crate::endpoint_lib::bdd_interpreter::BddNode; 6] = [
380 crate::endpoint_lib::bdd_interpreter::BddNode {
381 condition_index: -1,
382 high_ref: 1,
383 low_ref: -1,
384 },
385 crate::endpoint_lib::bdd_interpreter::BddNode {
386 condition_index: 0,
387 high_ref: 6,
388 low_ref: 3,
389 },
390 crate::endpoint_lib::bdd_interpreter::BddNode {
391 condition_index: 1,
392 high_ref: 4,
393 low_ref: 100000005,
394 },
395 crate::endpoint_lib::bdd_interpreter::BddNode {
396 condition_index: 2,
397 high_ref: 5,
398 low_ref: 100000005,
399 },
400 crate::endpoint_lib::bdd_interpreter::BddNode {
401 condition_index: 3,
402 high_ref: 100000003,
403 low_ref: 100000004,
404 },
405 crate::endpoint_lib::bdd_interpreter::BddNode {
406 condition_index: 3,
407 high_ref: 100000001,
408 low_ref: 100000002,
409 },
410];
411#[derive(Default)]
414#[allow(unused_lifetimes)]
415pub(crate) struct ConditionContext<'a> {
416 pub(crate) partition_result: Option<crate::endpoint_lib::partition::Partition<'a>>,
417 phantom: std::marker::PhantomData<&'a ()>,
419}
420
421#[non_exhaustive]
422#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::fmt::Debug)]
423pub struct Params {
425 pub(crate) use_fips: bool,
427 pub(crate) endpoint: ::std::option::Option<::std::string::String>,
429 pub(crate) region: ::std::option::Option<::std::string::String>,
431}
432impl Params {
433 pub fn builder() -> crate::config::endpoint::ParamsBuilder {
435 crate::config::endpoint::ParamsBuilder::default()
436 }
437 pub fn use_fips(&self) -> ::std::option::Option<bool> {
439 Some(self.use_fips)
440 }
441 pub fn endpoint(&self) -> ::std::option::Option<&str> {
443 self.endpoint.as_deref()
444 }
445 pub fn region(&self) -> ::std::option::Option<&str> {
447 self.region.as_deref()
448 }
449}
450
451#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::default::Default, ::std::fmt::Debug)]
453pub struct ParamsBuilder {
454 use_fips: ::std::option::Option<bool>,
455 endpoint: ::std::option::Option<::std::string::String>,
456 region: ::std::option::Option<::std::string::String>,
457}
458impl ParamsBuilder {
459 pub fn build(self) -> ::std::result::Result<crate::config::endpoint::Params, crate::config::endpoint::InvalidParams> {
461 if let Some(region) = &self.region {
462 if !crate::endpoint_lib::host::is_valid_host_label(
463 region.as_ref() as &str,
464 true,
465 &mut crate::endpoint_lib::diagnostic::DiagnosticCollector::new(),
466 ) {
467 return Err(crate::config::endpoint::InvalidParams::invalid_value(
468 "region",
469 "must be a valid host label",
470 ));
471 }
472 };
473 Ok(
474 #[allow(clippy::unnecessary_lazy_evaluations)]
475 crate::config::endpoint::Params {
476 use_fips: self
477 .use_fips
478 .or_else(|| Some(false))
479 .ok_or_else(|| crate::config::endpoint::InvalidParams::missing("use_fips"))?,
480 endpoint: self.endpoint,
481 region: self.region,
482 },
483 )
484 }
485 pub fn use_fips(mut self, value: impl Into<bool>) -> Self {
490 self.use_fips = Some(value.into());
491 self
492 }
493
494 pub fn set_use_fips(mut self, param: Option<bool>) -> Self {
499 self.use_fips = param;
500 self
501 }
502 pub fn endpoint(mut self, value: impl Into<::std::string::String>) -> Self {
506 self.endpoint = Some(value.into());
507 self
508 }
509
510 pub fn set_endpoint(mut self, param: Option<::std::string::String>) -> Self {
514 self.endpoint = param;
515 self
516 }
517 pub fn region(mut self, value: impl Into<::std::string::String>) -> Self {
521 self.region = Some(value.into());
522 self
523 }
524
525 pub fn set_region(mut self, param: Option<::std::string::String>) -> Self {
529 self.region = param;
530 self
531 }
532}
533
534#[derive(Debug)]
536pub struct InvalidParams {
537 field: std::borrow::Cow<'static, str>,
538 kind: InvalidParamsErrorKind,
539}
540
541#[derive(Debug)]
543enum InvalidParamsErrorKind {
544 MissingField,
545 InvalidValue { message: &'static str },
546}
547
548impl InvalidParams {
549 #[allow(dead_code)]
550 fn missing(field: &'static str) -> Self {
551 Self {
552 field: field.into(),
553 kind: InvalidParamsErrorKind::MissingField,
554 }
555 }
556
557 #[allow(dead_code)]
558 fn invalid_value(field: &'static str, message: &'static str) -> Self {
559 Self {
560 field: field.into(),
561 kind: InvalidParamsErrorKind::InvalidValue { message },
562 }
563 }
564}
565
566impl std::fmt::Display for InvalidParams {
567 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
568 match self.kind {
569 InvalidParamsErrorKind::MissingField => write!(f, "a required field was missing: `{}`", self.field),
570 InvalidParamsErrorKind::InvalidValue { message } => write!(f, "invalid value for field: `{}` - {}", self.field, message),
571 }
572 }
573}
574
575impl std::error::Error for InvalidParams {}