diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 8a50fded0f445739cabad62564df4dc5d5a96ac1..d546c0b6f0894f4b3410b5f8b26cf540972e6666 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 20217b2db20ab7ef4a0cdaf5087e492d823f081c..131c6d274fc85ed695a4cdb1b215737a6f4aa8c1 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 81cc1918a485391d78a013ba916a3d4738697211..84dde1e3c3b0c00929ede9aa5d0a686e122fdc6a 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.