From e652d6a6934560f356a04e442235fc9bc29e8d3f Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Thu, 4 Jan 2024 16:45:11 -0500 Subject: [PATCH] Add 'as-service-error' to simplify handling of specific error conditions (#3333) ## Motivation and Context aws-sdk-rust#1010 ## Description Add `as-service-error` helper function to cleanup handling of service error ## Testing UT ## Checklist - [x] I have updated `CHANGELOG.next.toml` if I made changes to the smithy-rs codegen or runtime crates - [x] I have updated `CHANGELOG.next.toml` if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._ --- CHANGELOG.next.toml | 12 ++++++++ .../s3/tests/status-200-errors.rs | 4 ++- .../src/client/result.rs | 30 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 8a50fded0..d546c0b6f 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -63,6 +63,18 @@ references = ["smithy-rs#3252", "smithy-rs#3312"] meta = { "breaking" = false, "tada" = false, "bug" = true } author = "milesziemer" +[[smithy-rs]] +message = "Add `as_service_err()` to `SdkError` to allow checking the type of an error is without taking ownership." +references = ["smithy-rs#3333", "aws-sdk-rust#998", "aws-sdk-rust#1010"] +meta = { "breaking" = false, "tada" = true, "bug" = false } +author = "rcoh" + +[[aws-sdk-rust]] +message = "Add `as_service_err()` to `SdkError` to allow checking the type of an error is without taking ownership." +references = ["smithy-rs#3333", "aws-sdk-rust#998", "aws-sdk-rust#1010"] +meta = { "breaking" = false, "tada" = true, "bug" = false } +author = "rcoh" + [[smithy-rs]] message = """`requireEndpointResolver: false` is no longer required to remove the need for an endpoint resolver. Instead, `"awsSdkBuilder"` (default false), now _removes_ that requirement.""" references = ["smithy-rs#3292"] diff --git a/aws/sdk/integration-tests/s3/tests/status-200-errors.rs b/aws/sdk/integration-tests/s3/tests/status-200-errors.rs index 20217b2db..131c6d274 100644 --- a/aws/sdk/integration-tests/s3/tests/status-200-errors.rs +++ b/aws/sdk/integration-tests/s3/tests/status-200-errors.rs @@ -6,6 +6,7 @@ use aws_credential_types::provider::SharedCredentialsProvider; use aws_credential_types::Credentials; use aws_sdk_s3::Client; +use aws_smithy_runtime::assert_str_contains; use aws_smithy_runtime::client::http::test_util::infallible_client_fn; use aws_smithy_types::body::SdkBody; use aws_smithy_types::error::metadata::ProvideErrorMetadata; @@ -37,5 +38,6 @@ async fn status_200_errors() { .send() .await .expect_err("should fail"); - assert_eq!(error.into_service_error().code(), Some("SlowDown")); + assert_eq!(error.as_service_error().unwrap().code(), Some("SlowDown")); + assert_str_contains!(format!("{:?}", error), "Please reduce your request rate"); } diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/result.rs b/rust-runtime/aws-smithy-runtime-api/src/client/result.rs index 81cc1918a..84dde1e3c 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/result.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/result.rs @@ -412,6 +412,36 @@ impl SdkError { } } + /// Returns a reference underlying service error `E` if there is one + /// + /// # Examples + /// ```no_run + /// # use aws_smithy_runtime_api::client::result::SdkError; + /// # #[derive(Debug)] enum GetObjectError { NoSuchKey(()), Other(()) } + /// # impl std::fmt::Display for GetObjectError { + /// # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { unimplemented!() } + /// # } + /// # impl std::error::Error for GetObjectError {} + /// # impl GetObjectError { + /// # fn is_not_found(&self) -> bool { true } + /// # } + /// # fn example() -> Result<(), GetObjectError> { + /// # let sdk_err = SdkError::service_error(GetObjectError::NoSuchKey(()), ()); + /// if sdk_err.as_service_error().map(|e|e.is_not_found()) == Some(true) { + /// println!("the object doesn't exist"); + /// // return None, or handle this error specifically + /// } + /// // ... handle other error cases, happy path, etc. + /// # Ok(()) + /// # } + /// ``` + pub fn as_service_error(&self) -> Option<&E> { + match self { + Self::ServiceError(err) => Some(&err.source), + _ => None, + } + } + /// Converts this error into its error source. /// /// If there is no error source, then `Err(Self)` is returned. -- GitLab