From 307f0ed11267c02854a69a58ce7cc19751c6131f Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Thu, 19 Oct 2023 10:15:25 -0400 Subject: [PATCH 1/5] Upgrade Smithy to 1.40 and ignore __type in unions (#3081) ## Motivation and Context > JSON object. A union is serialized identically as a ``structure`` shape, but only a single member can be set to a non-null value. Deserializers MUST ignore an unrecognized ``__type`` member if present. [source](https://github.com/smithy-lang/smithy/blob/main/docs/source-2.0/aws/protocols/aws-json.rst.template#L133-L135) ## Description - upgrade to smithy 1.40 - unignore protocol tests - fix JSON deserializers ## Testing - protocol tests + extra unit tests ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._ --- codegen-client-test/model/rest-xml-extras.smithy | 3 --- .../generators/protocol/ProtocolTestGenerator.kt | 3 --- .../smithy/protocols/parse/JsonParserGenerator.kt | 7 ++++++- .../smithy/protocols/parse/JsonParserGeneratorTest.kt | 11 +++++++++++ gradle.properties | 2 +- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/codegen-client-test/model/rest-xml-extras.smithy b/codegen-client-test/model/rest-xml-extras.smithy index 76a6bbd9fa8..b518ad09c69 100644 --- a/codegen-client-test/model/rest-xml-extras.smithy +++ b/codegen-client-test/model/rest-xml-extras.smithy @@ -74,9 +74,6 @@ structure PrimitiveIntDocument { defaultedValue: PrimitiveInt } -@enum([{"value": "enumvalue", "name": "V"}]) -string StringEnum - integer PrimitiveInt structure AttributePartyInputOutput { diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt index 9b256bbfce2..a188d3c9484 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt @@ -543,9 +543,6 @@ class DefaultProtocolTestGenerator( "SDKAppliedContentEncoding_ec2Query", "SDKAppliedContentEncoding_restJson1", "SDKAppliedContentEncoding_restXml", - "AwsJson11DeserializeIgnoreType", - "AwsJson10DeserializeIgnoreType", - "RestJsonDeserializeIgnoreType", ) } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt index 0e3f531971f..6b0a7b507bd 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt @@ -551,13 +551,18 @@ class JsonParserGenerator( objectKeyLoop(hasMembers = shape.members().isNotEmpty()) { rustTemplate( """ + let key = key.to_unescaped()?; + if key == "__type" { + #{skip_value}(tokens)?; + continue + } if variant.is_some() { return Err(#{Error}::custom("encountered mixed variants in union")); } """, *codegenScope, ) - withBlock("variant = match key.to_unescaped()?.as_ref() {", "};") { + withBlock("variant = match key.as_ref() {", "};") { for (member in shape.members()) { val variantName = symbolProvider.toMemberName(member) rustBlock("${jsonName(member).dq()} =>") { diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt index 108207473ff..e5ca4d19aee 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt @@ -170,6 +170,17 @@ class JsonParserGeneratorTest { """, ) + unitTest( + "dunder_type_should_be_ignored", + """ + // __type field should be ignored during deserialization + let input = br#"{ "top": { "choice": { "int": 5, "__type": "value-should-be-ignored-anyway" } } }"#; + let output = ${format(operationGenerator)}(input, test_output::OpOutput::builder()).unwrap().build(); + use test_model::Choice; + assert_eq!(Choice::Int(5), output.top.unwrap().choice); + """, + ) + unitTest( "empty_error", """ diff --git a/gradle.properties b/gradle.properties index 1db16fc661d..33e82bc2ca1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ kotlin.code.style=official # codegen smithyGradlePluginVersion=0.7.0 -smithyVersion=1.39.0 +smithyVersion=1.40.0 # kotlin kotlinVersion=1.7.21 From e447a22794d904d3b76567219c55e8a250f82a82 Mon Sep 17 00:00:00 2001 From: ysaito1001 Date: Thu, 19 Oct 2023 13:38:25 -0500 Subject: [PATCH 2/5] Re-point those using `BuildError` from smithy-http to smithy-types (#3070) ## Motivation and Context Completes #3054 (a follow-up on #3032) ## Description #3032 moved `BuildError` from `aws_smithy_http::operation::error` to `aws_smithy_types::error::operation`. That PR also left "breadcrumbs", so that customers could still consume `BuldError` from `aws_smithy_http` after the move. This PR turns breadcrumbs into deprecation messages (via `#[deprecated(...)]`) and updates existing places that used to use moved types from `aws_smithy_http` to `aws_smithy_types`. ## Testing Relied on tests in CI. ## Checklist - [x] I have updated `CHANGELOG.next.toml` if I made changes to the smithy-rs codegen or 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._ --------- Co-authored-by: Russell Cohen --- CHANGELOG.next.toml | 8 ++++++++ aws/rust-runtime/aws-inlineable/Cargo.toml | 4 ++-- .../aws-inlineable/src/http_request_checksum.rs | 2 +- .../s3/tests/required-query-params.rs | 2 +- .../core/smithy/generators/BuilderGenerator.kt | 4 ++-- .../src/protocol/aws_json/rejection.rs | 2 +- .../src/protocol/rest_json_1/rejection.rs | 4 ++-- .../src/protocol/rest_xml/rejection.rs | 4 ++-- rust-runtime/aws-smithy-http/src/operation.rs | 12 +++++++++--- 9 files changed, 28 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index c17e89a4cf9..b91b0009aa7 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -426,3 +426,11 @@ message = "**This change has [detailed upgrade guidance](https://github.com/awsl references = ["smithy-rs#3043", "smithy-rs#3078"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" } author = "rcoh" + +[[smithy-rs]] +message = """ +`aws_smithy_http::operation::error::{BuildError, SerializationError}` have been moved to `aws_smithy_types::error::operation::{BuildError, SerializationError}`. Type aliases for them are left in `aws_smithy_http` for backwards compatibility but are deprecated. +""" +references = ["smithy-rs#3054", "smithy-rs#3070"] +meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" } +author = "ysaito1001" diff --git a/aws/rust-runtime/aws-inlineable/Cargo.toml b/aws/rust-runtime/aws-inlineable/Cargo.toml index 56ccc8068e2..2e902d27760 100644 --- a/aws/rust-runtime/aws-inlineable/Cargo.toml +++ b/aws/rust-runtime/aws-inlineable/Cargo.toml @@ -16,12 +16,12 @@ aws-credential-types = { path = "../aws-credential-types" } aws-http = { path = "../aws-http" } aws-runtime = { path = "../aws-runtime" } aws-sigv4 = { path = "../aws-sigv4" } +aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async", features = ["rt-tokio"] } aws-smithy-checksums = { path = "../../../rust-runtime/aws-smithy-checksums" } aws-smithy-http = { path = "../../../rust-runtime/aws-smithy-http" } -aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] } aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["client"] } +aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] } aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" } -aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async", features = ["rt-tokio"] } bytes = "1" hex = "0.4.3" http = "0.2.9" diff --git a/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs b/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs index 3dc9cd449dd..b3a6f059b2d 100644 --- a/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs +++ b/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs @@ -13,7 +13,6 @@ use aws_sigv4::http_request::SignableBody; use aws_smithy_checksums::ChecksumAlgorithm; use aws_smithy_checksums::{body::calculate, http::HttpChecksum}; use aws_smithy_http::body::{BoxBody, SdkBody}; -use aws_smithy_http::operation::error::BuildError; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::interceptors::context::{ BeforeSerializationInterceptorContextRef, BeforeTransmitInterceptorContextMut, Input, @@ -23,6 +22,7 @@ use aws_smithy_runtime_api::client::interceptors::Intercept; use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_types::config_bag::{ConfigBag, Layer, Storable, StoreReplace}; +use aws_smithy_types::error::operation::BuildError; use http::HeaderValue; use http_body::Body; use std::{fmt, mem}; diff --git a/aws/sdk/integration-tests/s3/tests/required-query-params.rs b/aws/sdk/integration-tests/s3/tests/required-query-params.rs index 1df7f44e4e5..d9604260ea2 100644 --- a/aws/sdk/integration-tests/s3/tests/required-query-params.rs +++ b/aws/sdk/integration-tests/s3/tests/required-query-params.rs @@ -6,8 +6,8 @@ use aws_sdk_s3::config::{Credentials, Region}; use aws_sdk_s3::error::DisplayErrorContext; use aws_sdk_s3::Client; -use aws_smithy_http::operation::error::BuildError; use aws_smithy_runtime::client::http::test_util::capture_request; +use aws_smithy_types::error::operation::BuildError; #[tokio::test] async fn test_error_when_required_query_param_is_unset() { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt index 80b9329d636..9369423757b 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt @@ -75,8 +75,8 @@ sealed class BuilderSection(name: String) : Section(name) { /** Customizations for BuilderGenerator */ abstract class BuilderCustomization : NamedCustomization() -fun RuntimeConfig.operationBuildError() = RuntimeType.operationModule(this).resolve("error::BuildError") -fun RuntimeConfig.serializationError() = RuntimeType.operationModule(this).resolve("error::SerializationError") +fun RuntimeConfig.operationBuildError() = RuntimeType.smithyTypes(this).resolve("error::operation::BuildError") +fun RuntimeConfig.serializationError() = RuntimeType.smithyTypes(this).resolve("error::operation::SerializationError") fun MemberShape.enforceRequired( field: Writable, diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/rejection.rs b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/rejection.rs index 491e865dd6a..514b06da63b 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/rejection.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/rejection.rs @@ -9,7 +9,7 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum ResponseRejection { #[error("error serializing JSON-encoded body: {0}")] - Serialization(#[from] aws_smithy_http::operation::error::SerializationError), + Serialization(#[from] aws_smithy_types::error::operation::SerializationError), #[error("error building HTTP response: {0}")] HttpBuild(#[from] http::Error), } diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/rejection.rs b/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/rejection.rs index 8577d4a5571..963b56c4c1a 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/rejection.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/rejection.rs @@ -67,7 +67,7 @@ pub enum ResponseRejection { /// `httpHeader` or `httpPrefixHeaders`. /// Used when failing to serialize an `httpPayload`-bound struct into an HTTP response body. #[error("error building HTTP response: {0}")] - Build(#[from] aws_smithy_http::operation::error::BuildError), + Build(#[from] aws_smithy_types::error::operation::BuildError), /// Used when failing to serialize a struct into a `String` for the JSON-encoded HTTP response /// body. @@ -76,7 +76,7 @@ pub enum ResponseRejection { /// supplied timestamp is outside of the valid range when formatting using RFC-3339, i.e. a /// date outside the `0001-01-01T00:00:00.000Z`-`9999-12-31T23:59:59.999Z` range is supplied. #[error("error serializing JSON-encoded body: {0}")] - Serialization(#[from] aws_smithy_http::operation::error::SerializationError), + Serialization(#[from] aws_smithy_types::error::operation::SerializationError), /// Used when consuming an [`http::response::Builder`] into the constructed [`http::Response`] /// when calling [`http::response::Builder::body`]. diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/rejection.rs b/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/rejection.rs index 3e1bed00ca3..6c44adaa283 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/rejection.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/rejection.rs @@ -16,9 +16,9 @@ pub enum ResponseRejection { #[error("invalid bound HTTP status code; status codes must be inside the 100-999 range: {0}")] InvalidHttpStatusCode(TryFromIntError), #[error("error building HTTP response: {0}")] - Build(#[from] aws_smithy_http::operation::error::BuildError), + Build(#[from] aws_smithy_types::error::operation::BuildError), #[error("error serializing XML-encoded body: {0}")] - Serialization(#[from] aws_smithy_http::operation::error::SerializationError), + Serialization(#[from] aws_smithy_types::error::operation::SerializationError), #[error("error building HTTP response: {0}")] HttpBuild(#[from] http::Error), } diff --git a/rust-runtime/aws-smithy-http/src/operation.rs b/rust-runtime/aws-smithy-http/src/operation.rs index 0fed557b79b..7fad89f1e14 100644 --- a/rust-runtime/aws-smithy-http/src/operation.rs +++ b/rust-runtime/aws-smithy-http/src/operation.rs @@ -9,11 +9,17 @@ use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::borrow::Cow; -//TODO(runtimeCratesVersioningCleanup): Re-point those who use the following reexport to -// directly depend on `aws_smithy_types` and remove the reexport below. +//TODO(runtimeCratesVersioningCleanup): Re-point those who use the deprecated type aliases to +// directly depend on `aws_smithy_types` and remove the type aliases below. /// Errors for operations pub mod error { - pub use aws_smithy_types::error::operation::{BuildError, SerializationError}; + /// An error occurred attempting to build an `Operation` from an input. + #[deprecated(note = "Moved to `aws_smithy_types::error::operation::BuildError`.")] + pub type BuildError = aws_smithy_types::error::operation::BuildError; + + /// An error that occurs when serialization of an operation fails. + #[deprecated(note = "Moved to `aws_smithy_types::error::operation::SerializationError`.")] + pub type SerializationError = aws_smithy_types::error::operation::SerializationError; } /// Metadata added to the [`ConfigBag`](aws_smithy_types::config_bag::ConfigBag) that identifies the API being called. From ed8763e5df356d20b8b8df116c5e4a033f9b1b22 Mon Sep 17 00:00:00 2001 From: ysaito1001 Date: Thu, 19 Oct 2023 15:15:32 -0500 Subject: [PATCH 3/5] Re-point those using `ByteStream` and `SdkBody` to smithy-types (#3076) # Motivation and Context A follow-up on #3026 ## Description #3026 moved - `aws_smithy_http::body::{BoxBody, Error, SdkBody}` to `aws_smithy_types::body::{BoxBody, Error, SdkBody}` - `aws_smithy_http::byte_stream::{AggregatedBytes, ByteStream, error::Error}` to `aws_smithy_types::byte_stream::{AggregatedBytes, ByteStream, error::Error}` and also left "breadcrumbs", so that customers could still consume updated types from `aws_smithy_http` after the move. This PR turns breadcrumbs into deprecation messages (via `#[deprecated(...)]`) and updates existing places that used to use moved types from `aws_smithy_http` to directly depend on `aws_smithy_types`. ## Testing Relied on tests in CI. ## Checklist - [x] I have updated `CHANGELOG.next.toml` if I made changes to the smithy-rs codegen or 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 | 16 ++++++++ aws/rust-runtime/aws-config/src/ecs.rs | 2 +- .../src/http_credential_provider.rs | 4 +- .../aws-config/src/imds/client.rs | 4 +- .../aws-config/src/imds/client/error.rs | 2 +- .../aws-config/src/imds/client/token.rs | 2 +- .../aws-config/src/imds/credentials.rs | 2 +- .../aws-config/src/imds/region.rs | 2 +- aws/rust-runtime/aws-config/src/sso/token.rs | 2 +- .../aws-config/src/sts/assume_role.rs | 2 +- .../aws-http/src/content_encoding.rs | 8 ++-- aws/rust-runtime/aws-http/src/request_id.rs | 2 +- .../src/glacier_interceptors.rs | 3 +- .../src/http_request_checksum.rs | 7 ++-- .../src/http_response_checksum.rs | 6 +-- .../aws-inlineable/src/s3_request_id.rs | 2 +- .../aws-runtime/src/recursion_detection.rs | 2 +- .../aws-runtime/src/retries/classifiers.rs | 2 +- .../benchmark/src/multipart_get.rs | 2 +- .../benchmark/src/multipart_put.rs | 2 +- .../dynamodb/benches/deserialization_bench.rs | 2 +- .../dynamodb/tests/movies.rs | 2 +- .../dynamodb/tests/paginators.rs | 2 +- .../retries-with-client-rate-limiting.rs | 2 +- aws/sdk/integration-tests/ec2/Cargo.toml | 2 +- .../integration-tests/ec2/tests/paginators.rs | 2 +- .../kms/tests/integration.rs | 2 +- .../qldbsession/tests/integration.rs | 2 +- .../integration-tests/s3/tests/checksums.rs | 4 +- .../s3/tests/ignore-invalid-xml-body-root.rs | 2 +- .../integration-tests/s3/tests/request_id.rs | 2 +- .../tests/retry-classifier-customization.rs | 2 +- .../integration-tests/s3/tests/signing-it.rs | 2 +- .../s3/tests/status-200-errors.rs | 2 +- .../integration-tests/s3control/Cargo.toml | 2 +- .../s3control/tests/signing-it.rs | 2 +- .../integration-tests/webassembly/src/http.rs | 2 +- .../StreamingShapeSymbolProviderTest.kt | 4 +- .../generators/EndpointTraitBindingsTest.kt | 2 +- .../protocols/AwsQueryCompatibleTest.kt | 4 +- .../rust/codegen/core/rustlang/Writable.kt | 4 +- .../rust/codegen/core/smithy/RuntimeType.kt | 4 +- .../customizations/SmithyTypesPubUseExtra.kt | 8 ++-- .../SmithyTypesPubUseExtraTest.kt | 2 +- .../ServerHttpBoundProtocolGenerator.kt | 6 +-- .../smithy/protocols/ServerProtocolLoader.kt | 2 +- examples/pokemon-service-common/Cargo.toml | 2 +- examples/pokemon-service-common/src/lib.rs | 2 +- .../src/body/calculate.rs | 6 +-- .../aws-smithy-checksums/src/body/validate.rs | 8 ++-- .../src/pytests/bytestream.rs | 2 +- .../src/types.rs | 38 +++++++++---------- rust-runtime/aws-smithy-http/src/body.rs | 21 ++++++++++ .../aws-smithy-http/src/byte_stream.rs | 24 ++++++++++++ .../src/event_stream/receiver.rs | 4 +- .../src/futures_stream_adapter.rs | 6 +-- rust-runtime/aws-smithy-http/src/lib.rs | 7 +--- rust-runtime/aws-smithy-http/src/result.rs | 2 +- .../src/client/http/request.rs | 4 +- .../src/client/interceptors/context.rs | 2 +- .../src/client/orchestrator.rs | 2 +- .../src/client/runtime_plugin.rs | 2 +- .../src/client/auth/http.rs | 2 +- .../src/client/http/hyper_014.rs | 2 +- .../client/http/test_util/capture_request.rs | 2 +- .../src/client/http/test_util/dvr.rs | 4 +- .../src/client/http/test_util/dvr/record.rs | 2 +- .../src/client/http/test_util/dvr/replay.rs | 2 +- .../src/client/http/test_util/infallible.rs | 2 +- .../src/client/http/test_util/replay.rs | 2 +- .../src/client/interceptors.rs | 2 +- .../src/client/orchestrator.rs | 4 +- .../src/client/orchestrator/http.rs | 2 +- .../src/client/orchestrator/operation.rs | 2 +- .../src/client/retries/classifiers.rs | 2 +- .../tests/reconnect_on_transient_error.rs | 2 +- 76 files changed, 183 insertions(+), 127 deletions(-) create mode 100644 rust-runtime/aws-smithy-http/src/body.rs create mode 100644 rust-runtime/aws-smithy-http/src/byte_stream.rs diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index b91b0009aa7..cfeb53879e5 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -434,3 +434,19 @@ message = """ references = ["smithy-rs#3054", "smithy-rs#3070"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" } author = "ysaito1001" + +[[smithy-rs]] +message = """ +`aws_smithy_http::body::{BoxBody, Error, SdkBody}` have been moved to `aws_smithy_types::body::{BoxBody, Error, SdkBody}`. Type aliases for them are left in `aws_smithy_http` for backwards compatibility but are deprecated. +""" +references = ["smithy-rs#3076"] +meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" } +author = "ysaito1001" + +[[smithy-rs]] +message = """ +`aws_smithy_http::byte_stream::{AggregatedBytes, ByteStream, error::Error}` have been moved to `aws_smithy_types::byte_stream::{AggregatedBytes, ByteStream, error::Error}`. Type aliases for them are left in `aws_smithy_http` for backwards compatibility but are deprecated. +""" +references = ["smithy-rs#3076"] +meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all" } +author = "ysaito1001" diff --git a/aws/rust-runtime/aws-config/src/ecs.rs b/aws/rust-runtime/aws-config/src/ecs.rs index e8c709bf6d4..ed0125b69a2 100644 --- a/aws/rust-runtime/aws-config/src/ecs.rs +++ b/aws/rust-runtime/aws-config/src/ecs.rs @@ -442,11 +442,11 @@ mod test { use aws_credential_types::Credentials; use aws_smithy_async::future::never::Never; use aws_smithy_async::rt::sleep::TokioSleep; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; use aws_smithy_runtime_api::client::dns::DnsFuture; use aws_smithy_runtime_api::client::http::HttpClient; use aws_smithy_runtime_api::shared::IntoShared; + use aws_smithy_types::body::SdkBody; use aws_types::os_shim_internal::Env; use futures_util::FutureExt; use http::header::AUTHORIZATION; diff --git a/aws/rust-runtime/aws-config/src/http_credential_provider.rs b/aws/rust-runtime/aws-config/src/http_credential_provider.rs index e6dc79bd247..87687590cdd 100644 --- a/aws/rust-runtime/aws-config/src/http_credential_provider.rs +++ b/aws/rust-runtime/aws-config/src/http_credential_provider.rs @@ -12,7 +12,6 @@ use crate::json_credentials::{parse_json_credentials, JsonCredentials, Refreshab use crate::provider_config::ProviderConfig; use aws_credential_types::provider::{self, error::CredentialsError}; use aws_credential_types::Credentials; -use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::SdkError; use aws_smithy_runtime::client::orchestrator::operation::Operation; use aws_smithy_runtime::client::retries::classifiers::{ @@ -26,6 +25,7 @@ use aws_smithy_runtime_api::client::orchestrator::{ use aws_smithy_runtime_api::client::retries::classifiers::ClassifyRetry; use aws_smithy_runtime_api::client::retries::classifiers::RetryAction; use aws_smithy_runtime_api::client::runtime_plugin::StaticRuntimePlugin; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::Layer; use aws_smithy_types::retry::RetryConfig; use aws_smithy_types::timeout::TimeoutConfig; @@ -220,8 +220,8 @@ impl ClassifyRetry for HttpCredentialRetryClassifier { mod test { use super::*; use aws_credential_types::provider::error::CredentialsError; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; + use aws_smithy_types::body::SdkBody; use http::{Request, Response, Uri}; use std::time::SystemTime; diff --git a/aws/rust-runtime/aws-config/src/imds/client.rs b/aws/rust-runtime/aws-config/src/imds/client.rs index 823aa7c6369..e956193e384 100644 --- a/aws/rust-runtime/aws-config/src/imds/client.rs +++ b/aws/rust-runtime/aws-config/src/imds/client.rs @@ -13,7 +13,6 @@ use crate::provider_config::ProviderConfig; use crate::PKG_VERSION; use aws_http::user_agent::{ApiMetadata, AwsUserAgent}; use aws_runtime::user_agent::UserAgentInterceptor; -use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::ConnectorError; use aws_smithy_http::result::SdkError; use aws_smithy_runtime::client::orchestrator::operation::Operation; @@ -31,6 +30,7 @@ use aws_smithy_runtime_api::client::retries::classifiers::{ }; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder; use aws_smithy_runtime_api::client::runtime_plugin::{RuntimePlugin, SharedRuntimePlugin}; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::{FrozenLayer, Layer}; use aws_smithy_types::endpoint::Endpoint; use aws_smithy_types::retry::RetryConfig; @@ -583,7 +583,6 @@ pub(crate) mod test { use crate::provider_config::ProviderConfig; use aws_smithy_async::rt::sleep::TokioSleep; use aws_smithy_async::test_util::{instant_time_and_sleep, InstantSleep}; - use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::ConnectorError; use aws_smithy_runtime::client::http::test_util::{ capture_request, ReplayEvent, StaticReplayClient, @@ -596,6 +595,7 @@ pub(crate) mod test { HttpRequest, HttpResponse, OrchestratorError, }; use aws_smithy_runtime_api::client::retries::classifiers::{ClassifyRetry, RetryAction}; + use aws_smithy_types::body::SdkBody; use aws_smithy_types::error::display::DisplayErrorContext; use aws_types::os_shim_internal::{Env, Fs}; use http::header::USER_AGENT; diff --git a/aws/rust-runtime/aws-config/src/imds/client/error.rs b/aws/rust-runtime/aws-config/src/imds/client/error.rs index a97c3961c72..4b5aacb8946 100644 --- a/aws/rust-runtime/aws-config/src/imds/client/error.rs +++ b/aws/rust-runtime/aws-config/src/imds/client/error.rs @@ -5,10 +5,10 @@ //! Error types for [`ImdsClient`](crate::imds::client::Client) -use aws_smithy_http::body::SdkBody; use aws_smithy_http::endpoint::error::InvalidEndpointError; use aws_smithy_http::result::SdkError; use aws_smithy_runtime_api::client::orchestrator::HttpResponse; +use aws_smithy_types::body::SdkBody; use std::error::Error; use std::fmt; diff --git a/aws/rust-runtime/aws-config/src/imds/client/token.rs b/aws/rust-runtime/aws-config/src/imds/client/token.rs index 76b286583d1..57c0aeddd14 100644 --- a/aws/rust-runtime/aws-config/src/imds/client/token.rs +++ b/aws/rust-runtime/aws-config/src/imds/client/token.rs @@ -17,7 +17,6 @@ use crate::imds::client::error::{ImdsError, TokenError, TokenErrorKind}; use aws_credential_types::cache::ExpiringCache; use aws_smithy_async::time::SharedTimeSource; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::orchestrator::operation::Operation; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::auth::static_resolver::StaticAuthSchemeOptionResolver; @@ -32,6 +31,7 @@ use aws_smithy_runtime_api::client::runtime_components::{ GetIdentityResolver, RuntimeComponents, RuntimeComponentsBuilder, }; use aws_smithy_runtime_api::client::runtime_plugin::{RuntimePlugin, SharedRuntimePlugin}; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::ConfigBag; use http::{HeaderValue, Uri}; use std::borrow::Cow; diff --git a/aws/rust-runtime/aws-config/src/imds/credentials.rs b/aws/rust-runtime/aws-config/src/imds/credentials.rs index 52cf0bb6afb..845a53b8777 100644 --- a/aws/rust-runtime/aws-config/src/imds/credentials.rs +++ b/aws/rust-runtime/aws-config/src/imds/credentials.rs @@ -289,8 +289,8 @@ mod test { use crate::provider_config::ProviderConfig; use aws_credential_types::provider::ProvideCredentials; use aws_smithy_async::test_util::instant_time_and_sleep; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; + use aws_smithy_types::body::SdkBody; use std::time::{Duration, UNIX_EPOCH}; use tracing_test::traced_test; diff --git a/aws/rust-runtime/aws-config/src/imds/region.rs b/aws/rust-runtime/aws-config/src/imds/region.rs index bc19642a642..213e4a5c36b 100644 --- a/aws/rust-runtime/aws-config/src/imds/region.rs +++ b/aws/rust-runtime/aws-config/src/imds/region.rs @@ -111,8 +111,8 @@ mod test { use crate::imds::region::ImdsRegionProvider; use crate::provider_config::ProviderConfig; use aws_smithy_async::rt::sleep::TokioSleep; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; + use aws_smithy_types::body::SdkBody; use aws_types::region::Region; use tracing_test::traced_test; diff --git a/aws/rust-runtime/aws-config/src/sso/token.rs b/aws/rust-runtime/aws-config/src/sso/token.rs index b543fdc26f9..11870a241fa 100644 --- a/aws/rust-runtime/aws-config/src/sso/token.rs +++ b/aws/rust-runtime/aws-config/src/sso/token.rs @@ -389,13 +389,13 @@ mod tests { use aws_smithy_async::rt::sleep::TokioSleep; use aws_smithy_async::test_util::instant_time_and_sleep; use aws_smithy_async::time::{StaticTimeSource, TimeSource}; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ capture_request, ReplayEvent, StaticReplayClient, }; use aws_smithy_runtime::test_util::capture_test_logs::capture_test_logs; use aws_smithy_runtime_api::client::http::HttpClient; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder; + use aws_smithy_types::body::SdkBody; use aws_smithy_types::date_time::Format; use aws_smithy_types::retry::RetryConfig; use aws_smithy_types::DateTime; diff --git a/aws/rust-runtime/aws-config/src/sts/assume_role.rs b/aws/rust-runtime/aws-config/src/sts/assume_role.rs index 84c60c9a963..112358ec907 100644 --- a/aws/rust-runtime/aws-config/src/sts/assume_role.rs +++ b/aws/rust-runtime/aws-config/src/sts/assume_role.rs @@ -349,11 +349,11 @@ mod test { use aws_smithy_async::rt::sleep::{SharedAsyncSleep, TokioSleep}; use aws_smithy_async::test_util::instant_time_and_sleep; use aws_smithy_async::time::StaticTimeSource; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ capture_request, ReplayEvent, StaticReplayClient, }; use aws_smithy_runtime::test_util::capture_test_logs::capture_test_logs; + use aws_smithy_types::body::SdkBody; use aws_types::os_shim_internal::Env; use aws_types::region::Region; use aws_types::SdkConfig; diff --git a/aws/rust-runtime/aws-http/src/content_encoding.rs b/aws/rust-runtime/aws-http/src/content_encoding.rs index 6b900ab7506..dc9c62a1c7a 100644 --- a/aws/rust-runtime/aws-http/src/content_encoding.rs +++ b/aws/rust-runtime/aws-http/src/content_encoding.rs @@ -199,10 +199,10 @@ fn total_rendered_length_of_trailers(trailer_map: Option<&HeaderMap>) -> u64 { impl Body for AwsChunkedBody where - Inner: Body, + Inner: Body, { type Data = Bytes; - type Error = aws_smithy_http::body::Error; + type Error = aws_smithy_types::body::Error; fn poll_data( self: Pin<&mut Self>, @@ -354,7 +354,7 @@ mod tests { AwsChunkedBodyOptions, CHUNK_TERMINATOR, CRLF, }; - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; use bytes::{Buf, Bytes}; use bytes_utils::SegmentedBuf; use http::{HeaderMap, HeaderValue}; @@ -382,7 +382,7 @@ mod tests { impl Body for SputteringBody { type Data = Bytes; - type Error = aws_smithy_http::body::Error; + type Error = aws_smithy_types::body::Error; fn poll_data( self: Pin<&mut Self>, diff --git a/aws/rust-runtime/aws-http/src/request_id.rs b/aws/rust-runtime/aws-http/src/request_id.rs index 692e9cc86f5..a7b429169fb 100644 --- a/aws/rust-runtime/aws-http/src/request_id.rs +++ b/aws/rust-runtime/aws-http/src/request_id.rs @@ -94,7 +94,7 @@ fn extract_request_id(headers: &HeaderMap) -> Option<&str> { #[cfg(test)] mod tests { use super::*; - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; use http::Response; #[test] diff --git a/aws/rust-runtime/aws-inlineable/src/glacier_interceptors.rs b/aws/rust-runtime/aws-inlineable/src/glacier_interceptors.rs index 7cb27aaa1b6..845b2ef21fe 100644 --- a/aws/rust-runtime/aws-inlineable/src/glacier_interceptors.rs +++ b/aws/rust-runtime/aws-inlineable/src/glacier_interceptors.rs @@ -15,15 +15,14 @@ use ring::digest::{Context, Digest, SHA256}; use aws_runtime::auth::SigV4OperationSigningConfig; use aws_sigv4::http_request::SignableBody; -use aws_smithy_http::byte_stream; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::interceptors::context::{ BeforeSerializationInterceptorContextMut, BeforeTransmitInterceptorContextMut, }; use aws_smithy_runtime_api::client::interceptors::Intercept; - use aws_smithy_runtime_api::client::orchestrator::{HttpRequest, LoadedRequestBody}; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; +use aws_smithy_types::byte_stream; use aws_smithy_types::config_bag::ConfigBag; /// The default account ID when none is set on an input diff --git a/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs b/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs index b3a6f059b2d..846fbb52741 100644 --- a/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs +++ b/aws/rust-runtime/aws-inlineable/src/http_request_checksum.rs @@ -12,15 +12,14 @@ use aws_runtime::auth::SigV4OperationSigningConfig; use aws_sigv4::http_request::SignableBody; use aws_smithy_checksums::ChecksumAlgorithm; use aws_smithy_checksums::{body::calculate, http::HttpChecksum}; -use aws_smithy_http::body::{BoxBody, SdkBody}; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::interceptors::context::{ BeforeSerializationInterceptorContextRef, BeforeTransmitInterceptorContextMut, Input, }; use aws_smithy_runtime_api::client::interceptors::Intercept; - use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; +use aws_smithy_types::body::{BoxBody, SdkBody}; use aws_smithy_types::config_bag::{ConfigBag, Layer, Storable, StoreReplace}; use aws_smithy_types::error::operation::BuildError; use http::HeaderValue; @@ -214,10 +213,10 @@ fn wrap_streaming_request_body_in_checksum_calculating_body( mod tests { use crate::http_request_checksum::wrap_streaming_request_body_in_checksum_calculating_body; use aws_smithy_checksums::ChecksumAlgorithm; - use aws_smithy_http::body::SdkBody; - use aws_smithy_http::byte_stream::ByteStream; use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_types::base64; + use aws_smithy_types::body::SdkBody; + use aws_smithy_types::byte_stream::ByteStream; use bytes::BytesMut; use http_body::Body; use tempfile::NamedTempFile; diff --git a/aws/rust-runtime/aws-inlineable/src/http_response_checksum.rs b/aws/rust-runtime/aws-inlineable/src/http_response_checksum.rs index e9663b1deca..d770b44bf33 100644 --- a/aws/rust-runtime/aws-inlineable/src/http_response_checksum.rs +++ b/aws/rust-runtime/aws-inlineable/src/http_response_checksum.rs @@ -8,13 +8,13 @@ //! Interceptor for handling Smithy `@httpChecksum` response checksumming use aws_smithy_checksums::ChecksumAlgorithm; -use aws_smithy_http::body::{BoxBody, SdkBody}; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::interceptors::context::{ BeforeDeserializationInterceptorContextMut, BeforeSerializationInterceptorContextRef, Input, }; use aws_smithy_runtime_api::client::interceptors::Intercept; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; +use aws_smithy_types::body::{BoxBody, SdkBody}; use aws_smithy_types::config_bag::{ConfigBag, Layer, Storable, StoreReplace}; use http::HeaderValue; use std::{fmt, mem}; @@ -219,8 +219,8 @@ fn is_part_level_checksum(checksum: &str) -> bool { #[cfg(test)] mod tests { use super::{is_part_level_checksum, wrap_body_with_checksum_validator}; - use aws_smithy_http::body::SdkBody; - use aws_smithy_http::byte_stream::ByteStream; + use aws_smithy_types::body::SdkBody; + use aws_smithy_types::byte_stream::ByteStream; use aws_smithy_types::error::display::DisplayErrorContext; use bytes::Bytes; diff --git a/aws/rust-runtime/aws-inlineable/src/s3_request_id.rs b/aws/rust-runtime/aws-inlineable/src/s3_request_id.rs index 226eed5f7a3..93d2d850fe5 100644 --- a/aws/rust-runtime/aws-inlineable/src/s3_request_id.rs +++ b/aws/rust-runtime/aws-inlineable/src/s3_request_id.rs @@ -94,8 +94,8 @@ fn extract_extended_request_id(headers: &HeaderMap) -> Option<&str> #[cfg(test)] mod test { use super::*; - use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::SdkError; + use aws_smithy_types::body::SdkBody; use http::Response; #[test] diff --git a/aws/rust-runtime/aws-runtime/src/recursion_detection.rs b/aws/rust-runtime/aws-runtime/src/recursion_detection.rs index b37ad2f5d12..21239e9c3ba 100644 --- a/aws/rust-runtime/aws-runtime/src/recursion_detection.rs +++ b/aws/rust-runtime/aws-runtime/src/recursion_detection.rs @@ -78,10 +78,10 @@ fn encode_header(value: &[u8]) -> HeaderValue { #[cfg(test)] mod tests { use super::*; - use aws_smithy_http::body::SdkBody; use aws_smithy_protocol_test::{assert_ok, validate_headers}; use aws_smithy_runtime_api::client::interceptors::context::{Input, InterceptorContext}; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder; + use aws_smithy_types::body::SdkBody; use aws_types::os_shim_internal::Env; use http::HeaderValue; use proptest::{prelude::*, proptest}; diff --git a/aws/rust-runtime/aws-runtime/src/retries/classifiers.rs b/aws/rust-runtime/aws-runtime/src/retries/classifiers.rs index 7dcb4f9a86a..11c4346bbad 100644 --- a/aws/rust-runtime/aws-runtime/src/retries/classifiers.rs +++ b/aws/rust-runtime/aws-runtime/src/retries/classifiers.rs @@ -111,11 +111,11 @@ where #[cfg(test)] mod test { use crate::retries::classifiers::AwsErrorCodeClassifier; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::interceptors::context::InterceptorContext; use aws_smithy_runtime_api::client::interceptors::context::{Error, Input}; use aws_smithy_runtime_api::client::orchestrator::OrchestratorError; use aws_smithy_runtime_api::client::retries::classifiers::{ClassifyRetry, RetryAction}; + use aws_smithy_types::body::SdkBody; use aws_smithy_types::error::metadata::ProvideErrorMetadata; use aws_smithy_types::error::ErrorMetadata; use aws_smithy_types::retry::ErrorKind; diff --git a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs index ab8832816cd..10e209776e0 100644 --- a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs +++ b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs @@ -8,7 +8,7 @@ use async_trait::async_trait; use aws_config::SdkConfig; use aws_sdk_s3 as s3; use aws_sdk_s3::Client; -use aws_smithy_http::byte_stream::AggregatedBytes; +use aws_smithy_types::byte_stream::AggregatedBytes; use std::fmt; use std::fs::File; use std::os::unix::fs::FileExt; diff --git a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs index 942c3d80208..d5bc8c8a974 100644 --- a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs +++ b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs @@ -9,7 +9,7 @@ use async_trait::async_trait; use aws_config::SdkConfig; use aws_sdk_s3 as s3; use aws_sdk_s3::Client; -use aws_smithy_http::byte_stream::ByteStream; +use aws_smithy_types::byte_stream::ByteStream; use s3::types::CompletedMultipartUpload; use s3::types::CompletedPart; use std::io::SeekFrom; diff --git a/aws/sdk/integration-tests/dynamodb/benches/deserialization_bench.rs b/aws/sdk/integration-tests/dynamodb/benches/deserialization_bench.rs index 58d3db07020..cf4b58e646c 100644 --- a/aws/sdk/integration-tests/dynamodb/benches/deserialization_bench.rs +++ b/aws/sdk/integration-tests/dynamodb/benches/deserialization_bench.rs @@ -4,9 +4,9 @@ */ use aws_sdk_dynamodb::operation::query::QueryOutput; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::runtime_plugin::RuntimePlugin; use aws_smithy_runtime_api::client::ser_de::{ResponseDeserializer, SharedResponseDeserializer}; +use aws_smithy_types::body::SdkBody; use criterion::{criterion_group, criterion_main, Criterion}; fn do_bench() { diff --git a/aws/sdk/integration-tests/dynamodb/tests/movies.rs b/aws/sdk/integration-tests/dynamodb/tests/movies.rs index 28801001065..6254dd6ece4 100644 --- a/aws/sdk/integration-tests/dynamodb/tests/movies.rs +++ b/aws/sdk/integration-tests/dynamodb/tests/movies.rs @@ -5,8 +5,8 @@ use aws_sdk_dynamodb as dynamodb; use aws_smithy_async::assert_elapsed; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +use aws_smithy_types::body::SdkBody; use dynamodb::config::{Credentials, Region}; use dynamodb::operation::query::QueryOutput; use dynamodb::types::{ diff --git a/aws/sdk/integration-tests/dynamodb/tests/paginators.rs b/aws/sdk/integration-tests/dynamodb/tests/paginators.rs index 711feb1e019..7cb07f07672 100644 --- a/aws/sdk/integration-tests/dynamodb/tests/paginators.rs +++ b/aws/sdk/integration-tests/dynamodb/tests/paginators.rs @@ -9,12 +9,12 @@ use std::iter::FromIterator; use aws_credential_types::Credentials; use aws_sdk_dynamodb::types::AttributeValue; use aws_sdk_dynamodb::{Client, Config}; -use aws_smithy_http::body::SdkBody; use aws_smithy_protocol_test::{assert_ok, validate_body, MediaType}; use aws_smithy_runtime::client::http::test_util::{ capture_request, ReplayEvent, StaticReplayClient, }; use aws_smithy_runtime_api::client::http::HttpClient; +use aws_smithy_types::body::SdkBody; use aws_types::region::Region; fn stub_config(http_client: impl HttpClient + 'static) -> Config { diff --git a/aws/sdk/integration-tests/dynamodb/tests/retries-with-client-rate-limiting.rs b/aws/sdk/integration-tests/dynamodb/tests/retries-with-client-rate-limiting.rs index 225bbabebdd..bb87a2626ea 100644 --- a/aws/sdk/integration-tests/dynamodb/tests/retries-with-client-rate-limiting.rs +++ b/aws/sdk/integration-tests/dynamodb/tests/retries-with-client-rate-limiting.rs @@ -7,10 +7,10 @@ use aws_sdk_dynamodb::config::{Credentials, Region, SharedAsyncSleep}; use aws_sdk_dynamodb::{config::retry::RetryConfig, error::ProvideErrorMetadata}; use aws_smithy_async::test_util::instant_time_and_sleep; use aws_smithy_async::time::SharedTimeSource; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; use aws_smithy_runtime::client::retries::RetryPartition; use aws_smithy_runtime_api::client::orchestrator::HttpResponse; +use aws_smithy_types::body::SdkBody; use std::time::{Duration, SystemTime}; fn req() -> http::Request { diff --git a/aws/sdk/integration-tests/ec2/Cargo.toml b/aws/sdk/integration-tests/ec2/Cargo.toml index 9e2757bea22..a3a44d610c1 100644 --- a/aws/sdk/integration-tests/ec2/Cargo.toml +++ b/aws/sdk/integration-tests/ec2/Cargo.toml @@ -9,9 +9,9 @@ publish = false [dev-dependencies] aws-credential-types = { path = "../../build/aws-sdk/sdk/aws-credential-types", features = ["test-util"] } aws-smithy-async = { path = "../../build/aws-sdk/sdk/aws-smithy-async" } -aws-smithy-http = { path = "../../build/aws-sdk/sdk/aws-smithy-http" } aws-smithy-runtime = { path = "../../build/aws-sdk/sdk/aws-smithy-runtime", features = ["client", "test-util"] } aws-smithy-runtime-api = { path = "../../build/aws-sdk/sdk/aws-smithy-runtime-api", features = ["client"] } +aws-smithy-types = { path = "../../build/aws-sdk/sdk/aws-smithy-types" } aws-sdk-ec2 = { path = "../../build/aws-sdk/sdk/ec2" } tokio = { version = "1.23.1", features = ["full"]} http = "0.2.0" diff --git a/aws/sdk/integration-tests/ec2/tests/paginators.rs b/aws/sdk/integration-tests/ec2/tests/paginators.rs index a9ab25a4a1a..0ab3be626cb 100644 --- a/aws/sdk/integration-tests/ec2/tests/paginators.rs +++ b/aws/sdk/integration-tests/ec2/tests/paginators.rs @@ -4,9 +4,9 @@ */ use aws_sdk_ec2::{config::Credentials, config::Region, types::InstanceType, Client, Config}; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; use aws_smithy_runtime_api::client::http::HttpClient; +use aws_smithy_types::body::SdkBody; fn stub_config(http_client: impl HttpClient + 'static) -> Config { Config::builder() diff --git a/aws/sdk/integration-tests/kms/tests/integration.rs b/aws/sdk/integration-tests/kms/tests/integration.rs index 624dfd9d396..1227eb24bc5 100644 --- a/aws/sdk/integration-tests/kms/tests/integration.rs +++ b/aws/sdk/integration-tests/kms/tests/integration.rs @@ -5,9 +5,9 @@ use aws_sdk_kms as kms; use aws_sdk_kms::operation::RequestId; -use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::SdkError; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +use aws_smithy_types::body::SdkBody; use http::header::AUTHORIZATION; use http::Uri; use kms::config::{Config, Credentials, Region}; diff --git a/aws/sdk/integration-tests/qldbsession/tests/integration.rs b/aws/sdk/integration-tests/qldbsession/tests/integration.rs index 61f0a7e5395..6cdb32d1f17 100644 --- a/aws/sdk/integration-tests/qldbsession/tests/integration.rs +++ b/aws/sdk/integration-tests/qldbsession/tests/integration.rs @@ -8,8 +8,8 @@ use aws_sdk_qldbsession::config::{Config, Credentials, Region}; use aws_sdk_qldbsession::types::StartSessionRequest; use aws_sdk_qldbsession::Client; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +use aws_smithy_types::body::SdkBody; use http::Uri; #[cfg(feature = "test-util")] diff --git a/aws/sdk/integration-tests/s3/tests/checksums.rs b/aws/sdk/integration-tests/s3/tests/checksums.rs index b7b3d5be8a3..37782182e01 100644 --- a/aws/sdk/integration-tests/s3/tests/checksums.rs +++ b/aws/sdk/integration-tests/s3/tests/checksums.rs @@ -11,10 +11,10 @@ use aws_sdk_s3::config::{Credentials, Region}; use aws_sdk_s3::types::ChecksumMode; use aws_sdk_s3::{operation::get_object::GetObjectOutput, types::ChecksumAlgorithm}; use aws_sdk_s3::{Client, Config}; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ capture_request, ReplayEvent, StaticReplayClient, }; +use aws_smithy_types::body::SdkBody; use http::header::AUTHORIZATION; use http::{HeaderValue, Uri}; use std::time::{Duration, UNIX_EPOCH}; @@ -315,7 +315,7 @@ async fn test_sha256_checksum_on_streaming_request() { .await } -async fn collect_body_into_string(mut body: aws_smithy_http::body::SdkBody) -> String { +async fn collect_body_into_string(mut body: aws_smithy_types::body::SdkBody) -> String { use bytes::Buf; use bytes_utils::SegmentedBuf; use http_body::Body; diff --git a/aws/sdk/integration-tests/s3/tests/ignore-invalid-xml-body-root.rs b/aws/sdk/integration-tests/s3/tests/ignore-invalid-xml-body-root.rs index 3b8034a6739..89b15ba58c6 100644 --- a/aws/sdk/integration-tests/s3/tests/ignore-invalid-xml-body-root.rs +++ b/aws/sdk/integration-tests/s3/tests/ignore-invalid-xml-body-root.rs @@ -8,8 +8,8 @@ use aws_credential_types::provider::SharedCredentialsProvider; use aws_sdk_s3::Config; use aws_sdk_s3::{config::Credentials, config::Region, types::ObjectAttributes, Client}; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +use aws_smithy_types::body::SdkBody; use http::header::AUTHORIZATION; const RESPONSE_BODY_XML: &[u8] = b"\ne1AsOh9IyGCa4hLN+2Od7jlnP14="; diff --git a/aws/sdk/integration-tests/s3/tests/request_id.rs b/aws/sdk/integration-tests/s3/tests/request_id.rs index d46bfe66da1..1ea72044263 100644 --- a/aws/sdk/integration-tests/s3/tests/request_id.rs +++ b/aws/sdk/integration-tests/s3/tests/request_id.rs @@ -6,8 +6,8 @@ use aws_sdk_s3::operation::get_object::GetObjectError; use aws_sdk_s3::operation::{RequestId, RequestIdExt}; use aws_sdk_s3::{config::Credentials, config::Region, Client, Config}; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::capture_request; +use aws_smithy_types::body::SdkBody; #[tokio::test] async fn get_request_id_from_modeled_error() { diff --git a/aws/sdk/integration-tests/s3/tests/retry-classifier-customization.rs b/aws/sdk/integration-tests/s3/tests/retry-classifier-customization.rs index 15af1103694..cda97da3631 100644 --- a/aws/sdk/integration-tests/s3/tests/retry-classifier-customization.rs +++ b/aws/sdk/integration-tests/s3/tests/retry-classifier-customization.rs @@ -7,8 +7,8 @@ use aws_sdk_s3::config::interceptors::InterceptorContext; use aws_sdk_s3::config::retry::{ClassifyRetry, RetryAction, RetryConfig}; use aws_sdk_s3::config::SharedAsyncSleep; use aws_smithy_async::rt::sleep::TokioSleep; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +use aws_smithy_types::body::SdkBody; use std::sync::{Arc, Mutex}; #[derive(Debug, Clone)] diff --git a/aws/sdk/integration-tests/s3/tests/signing-it.rs b/aws/sdk/integration-tests/s3/tests/signing-it.rs index d690e31cf3f..450f4ba43ff 100644 --- a/aws/sdk/integration-tests/s3/tests/signing-it.rs +++ b/aws/sdk/integration-tests/s3/tests/signing-it.rs @@ -8,8 +8,8 @@ use aws_credential_types::provider::SharedCredentialsProvider; use aws_sdk_s3::config::{Credentials, Region}; use aws_sdk_s3::{Client, Config}; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +use aws_smithy_types::body::SdkBody; #[tokio::test] async fn test_signer() { 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 ad53f1fedbd..20217b2db20 100644 --- a/aws/sdk/integration-tests/s3/tests/status-200-errors.rs +++ b/aws/sdk/integration-tests/s3/tests/status-200-errors.rs @@ -6,8 +6,8 @@ use aws_credential_types::provider::SharedCredentialsProvider; use aws_credential_types::Credentials; use aws_sdk_s3::Client; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::infallible_client_fn; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::error::metadata::ProvideErrorMetadata; use aws_types::region::Region; use aws_types::SdkConfig; diff --git a/aws/sdk/integration-tests/s3control/Cargo.toml b/aws/sdk/integration-tests/s3control/Cargo.toml index cf1fd7f23b4..9bd9484f9b2 100644 --- a/aws/sdk/integration-tests/s3control/Cargo.toml +++ b/aws/sdk/integration-tests/s3control/Cargo.toml @@ -20,7 +20,7 @@ aws-http = { path = "../../build/aws-sdk/sdk/aws-http" } aws-sdk-s3control = { path = "../../build/aws-sdk/sdk/s3control", features = ["test-util"] } aws-smithy-async = { path = "../../build/aws-sdk/sdk/aws-smithy-async" } aws-smithy-runtime = { path = "../../build/aws-sdk/sdk/aws-smithy-runtime", features = ["client", "test-util"] } -aws-smithy-http = { path = "../../build/aws-sdk/sdk/aws-smithy-http" } +aws-smithy-types = { path = "../../build/aws-sdk/sdk/aws-smithy-types" } aws-types = { path = "../../build/aws-sdk/sdk/aws-types" } bytes = "1.0.0" http = "0.2.0" diff --git a/aws/sdk/integration-tests/s3control/tests/signing-it.rs b/aws/sdk/integration-tests/s3control/tests/signing-it.rs index 242f2f2d783..7917b836ebb 100644 --- a/aws/sdk/integration-tests/s3control/tests/signing-it.rs +++ b/aws/sdk/integration-tests/s3control/tests/signing-it.rs @@ -6,8 +6,8 @@ use aws_credential_types::provider::SharedCredentialsProvider; use aws_sdk_s3control::config::{Credentials, Region}; use aws_sdk_s3control::{Client, Config}; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +use aws_smithy_types::body::SdkBody; #[tokio::test] async fn test_signer() { diff --git a/aws/sdk/integration-tests/webassembly/src/http.rs b/aws/sdk/integration-tests/webassembly/src/http.rs index b13f4bf2b05..930ebaf5476 100644 --- a/aws/sdk/integration-tests/webassembly/src/http.rs +++ b/aws/sdk/integration-tests/webassembly/src/http.rs @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::http::{ HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpConnector, }; use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_types::body::SdkBody; pub(crate) fn make_request(_req: http::Request) -> Result, ()> { // Consumers here would pass the HTTP request to diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt index 61d97317f20..9846d9b0c00 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/StreamingShapeSymbolProviderTest.kt @@ -43,13 +43,13 @@ internal class StreamingShapeSymbolProviderTest { modelWithOperationTraits.lookup("test.synthetic#GenerateSpeechOutput\$data").also { shape -> symbolProvider.toSymbol(shape).also { symbol -> symbol.name shouldBe "data" - symbol.rustType() shouldBe RustType.Opaque("ByteStream", "::aws_smithy_http::byte_stream") + symbol.rustType() shouldBe RustType.Opaque("ByteStream", "::aws_smithy_types::byte_stream") } } modelWithOperationTraits.lookup("test.synthetic#GenerateSpeechInput\$data").also { shape -> symbolProvider.toSymbol(shape).also { symbol -> symbol.name shouldBe "data" - symbol.rustType() shouldBe RustType.Opaque("ByteStream", "::aws_smithy_http::byte_stream") + symbol.rustType() shouldBe RustType.Opaque("ByteStream", "::aws_smithy_types::byte_stream") } } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/EndpointTraitBindingsTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/EndpointTraitBindingsTest.kt index be5d38a0164..c645759040f 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/EndpointTraitBindingsTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/EndpointTraitBindingsTest.kt @@ -159,10 +159,10 @@ internal class EndpointTraitBindingsTest { """ async fn test_endpoint_prefix() { use #{capture_request}; - use aws_smithy_http::body::SdkBody; use aws_smithy_http::endpoint::EndpointPrefix; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; + use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::ConfigBag; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::{Arc, Mutex}; diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/AwsQueryCompatibleTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/AwsQueryCompatibleTest.kt index 64c7cae3ba8..706e7b81c01 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/AwsQueryCompatibleTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/AwsQueryCompatibleTest.kt @@ -58,7 +58,7 @@ class AwsQueryCompatibleTest { ##[cfg(test)] ##[#{tokio}::test] async fn should_parse_code_and_type_fields() { - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; let response = |_: http::Request| { http::Response::builder() @@ -138,7 +138,7 @@ class AwsQueryCompatibleTest { ##[cfg(test)] ##[#{tokio}::test] async fn should_parse_code_from_payload() { - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; let response = |_: http::Request| { http::Response::builder() diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt index a0c2c2f2452..8ef68e9ef25 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt @@ -95,14 +95,14 @@ fun Array.join(separator: Writable) = asIterable().join(separator) * "type_params" to rustTypeParameters( * symbolProvider.toSymbol(operation), * RustType.Unit, - * runtimeConfig.smithyHttp().resolve("body::SdkBody"), + * runtimeConfig.smithyTypes().resolve("body::SdkBody"), * GenericsGenerator(GenericTypeArg("A"), GenericTypeArg("B")), * ) * ) * ``` * would write out something like: * ```rust - * some_fn::(); + * some_fn::(); * ``` */ fun rustTypeParameters( diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt index d583a7d163b..7ccf2e9479b 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt @@ -394,7 +394,7 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) smithyRuntimeApi(runtimeConfig).resolve("client::interceptors::context::FinalizerInterceptorContextMut") fun blob(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("Blob") - fun byteStream(runtimeConfig: RuntimeConfig) = smithyHttp(runtimeConfig).resolve("byte_stream::ByteStream") + fun byteStream(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("byte_stream::ByteStream") fun dateTime(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("DateTime") fun document(runtimeConfig: RuntimeConfig): RuntimeType = smithyTypes(runtimeConfig).resolve("Document") fun format(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("date_time::Format") @@ -429,7 +429,7 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) smithyTypes(runtimeConfig).resolve("retry::ProvideErrorKind") fun queryFormat(runtimeConfig: RuntimeConfig, func: String) = smithyHttp(runtimeConfig).resolve("query::$func") - fun sdkBody(runtimeConfig: RuntimeConfig): RuntimeType = smithyHttp(runtimeConfig).resolve("body::SdkBody") + fun sdkBody(runtimeConfig: RuntimeConfig): RuntimeType = smithyTypes(runtimeConfig).resolve("body::SdkBody") fun sdkError(runtimeConfig: RuntimeConfig): RuntimeType = smithyHttp(runtimeConfig).resolve("result::SdkError") fun sdkSuccess(runtimeConfig: RuntimeConfig): RuntimeType = smithyHttp(runtimeConfig).resolve("result::SdkSuccess") diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt index 14d081b2cb7..d59b4a96231 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt @@ -64,10 +64,10 @@ fun pubUseSmithyPrimitives(codegenContext: CodegenContext, model: Model): Writab pub use #{Error} as ByteStreamError; pub use #{SdkBody}; """, - "ByteStream" to RuntimeType.smithyHttp(rc).resolve("byte_stream::ByteStream"), - "AggregatedBytes" to RuntimeType.smithyHttp(rc).resolve("byte_stream::AggregatedBytes"), - "Error" to RuntimeType.smithyHttp(rc).resolve("byte_stream::error::Error"), - "SdkBody" to RuntimeType.smithyHttp(rc).resolve("body::SdkBody"), + "ByteStream" to RuntimeType.smithyTypes(rc).resolve("byte_stream::ByteStream"), + "AggregatedBytes" to RuntimeType.smithyTypes(rc).resolve("byte_stream::AggregatedBytes"), + "Error" to RuntimeType.smithyTypes(rc).resolve("byte_stream::error::Error"), + "SdkBody" to RuntimeType.smithyTypes(rc).resolve("body::SdkBody"), ) } } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt index b02574e6a53..62a54905afe 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtraTest.kt @@ -105,7 +105,7 @@ class SmithyTypesPubUseExtraTest { @Test fun `it re-exports ByteStream and AggregatedBytes when a model has streaming`() { val streamingTypes = - listOf("::aws_smithy_http::byte_stream::ByteStream", "::aws_smithy_http::byte_stream::AggregatedBytes") + listOf("::aws_smithy_types::byte_stream::ByteStream", "::aws_smithy_types::byte_stream::AggregatedBytes") val streamingShape = "@streaming blob Streaming" this.assertDoesntHaveReexports(reexportsWithEmptyModel(), streamingTypes) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt index 11a9a9558ba..f8c18f39655 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt @@ -98,7 +98,7 @@ sealed class ServerHttpBoundProtocolSection(name: String) : Section(name) { * Represent a section for rendering the serialized stream payload. * * If the payload does not implement the `futures_core::stream::Stream`, which is the case for - * `aws_smithy_http::byte_stream::ByteStream`, the section needs to be overridden and renders a new-type wrapper + * `aws_smithy_types::byte_stream::ByteStream`, the section needs to be overridden and renders a new-type wrapper * around the payload to enable the `Stream` trait. */ data class WrapStreamPayload(val params: StreamPayloadSerializerParams) : @@ -189,8 +189,8 @@ class ServerHttpBoundProtocolTraitImplGenerator( "OnceCell" to RuntimeType.OnceCell, "PercentEncoding" to RuntimeType.PercentEncoding, "Regex" to RuntimeType.Regex, - "SmithyHttp" to RuntimeType.smithyHttp(runtimeConfig), "SmithyHttpServer" to ServerCargoDependency.smithyHttpServer(runtimeConfig).toType(), + "SmithyTypes" to RuntimeType.smithyTypes(runtimeConfig), "RuntimeError" to protocol.runtimeError(runtimeConfig), "RequestRejection" to protocol.requestRejection(runtimeConfig), "ResponseRejection" to protocol.responseRejection(runtimeConfig), @@ -1269,7 +1269,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( private fun streamingBodyTraitBounds(operationShape: OperationShape) = if (operationShape.inputShape(model).hasStreamingMember(model)) { - "\n B: Into<#{SmithyHttp}::byte_stream::ByteStream>," + "\n B: Into<#{SmithyTypes}::byte_stream::ByteStream>," } else { "" } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerProtocolLoader.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerProtocolLoader.kt index 92dde3b2f6d..a72ad201c0d 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerProtocolLoader.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerProtocolLoader.kt @@ -28,7 +28,7 @@ class StreamPayloadSerializerCustomization() : ServerHttpBoundProtocolCustomizat // implements the `Stream` trait, so no need to wrap it in the new-type. section.params.payloadGenerator.generatePayload(this, section.params.shapeName, section.params.shape) } else { - // Otherwise, the stream payload is `aws_smithy_http::byte_stream::ByteStream`. We wrap it in the + // Otherwise, the stream payload is `aws_smithy_types::byte_stream::ByteStream`. We wrap it in the // new-type to enable the `Stream` trait. withBlockTemplate( "#{FuturesStreamCompatByteStream}::new(", diff --git a/examples/pokemon-service-common/Cargo.toml b/examples/pokemon-service-common/Cargo.toml index 6a63045004f..e23a3c8dbf1 100644 --- a/examples/pokemon-service-common/Cargo.toml +++ b/examples/pokemon-service-common/Cargo.toml @@ -18,8 +18,8 @@ tower = "0.4" # Local paths aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime", features = ["client", "connector-hyper-0-14-x"] } aws-smithy-runtime-api = { path = "../../rust-runtime/aws-smithy-runtime-api", features = ["client"] } -aws-smithy-http = { path = "../../rust-runtime/aws-smithy-http" } aws-smithy-http-server = { path = "../../rust-runtime/aws-smithy-http-server" } +aws-smithy-types = { path = "../../rust-runtime/aws-smithy-types" } pokemon-service-client = { path = "../pokemon-service-client" } pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk" } diff --git a/examples/pokemon-service-common/src/lib.rs b/examples/pokemon-service-common/src/lib.rs index c4c8bc4e752..851a07865ba 100644 --- a/examples/pokemon-service-common/src/lib.rs +++ b/examples/pokemon-service-common/src/lib.rs @@ -15,10 +15,10 @@ use std::{ }; use async_stream::stream; -use aws_smithy_http::{body::SdkBody, byte_stream::ByteStream}; use aws_smithy_http_server::Extension; use aws_smithy_runtime::client::http::hyper_014::HyperConnector; use aws_smithy_runtime_api::client::http::HttpConnector; +use aws_smithy_types::{body::SdkBody, byte_stream::ByteStream}; use http::Uri; use pokemon_service_server_sdk::{ error, input, model, model::CapturingPayload, output, types::Blob, diff --git a/rust-runtime/aws-smithy-checksums/src/body/calculate.rs b/rust-runtime/aws-smithy-checksums/src/body/calculate.rs index 2ac3f09896a..8c9fcb368b0 100644 --- a/rust-runtime/aws-smithy-checksums/src/body/calculate.rs +++ b/rust-runtime/aws-smithy-checksums/src/body/calculate.rs @@ -7,8 +7,8 @@ use crate::http::HttpChecksum; -use aws_smithy_http::body::SdkBody; use aws_smithy_http::header::append_merge_header_maps; +use aws_smithy_types::body::SdkBody; use http::HeaderMap; use http_body::SizeHint; @@ -38,7 +38,7 @@ impl ChecksumBody { impl http_body::Body for ChecksumBody { type Data = bytes::Bytes; - type Error = aws_smithy_http::body::Error; + type Error = aws_smithy_types::body::Error; fn poll_data( self: Pin<&mut Self>, @@ -99,8 +99,8 @@ impl http_body::Body for ChecksumBody { mod tests { use super::ChecksumBody; use crate::{http::CRC_32_HEADER_NAME, ChecksumAlgorithm, CRC_32_NAME}; - use aws_smithy_http::body::SdkBody; use aws_smithy_types::base64; + use aws_smithy_types::body::SdkBody; use bytes::Buf; use bytes_utils::SegmentedBuf; use http_body::Body; diff --git a/rust-runtime/aws-smithy-checksums/src/body/validate.rs b/rust-runtime/aws-smithy-checksums/src/body/validate.rs index 5af263bf02b..cf15815772e 100644 --- a/rust-runtime/aws-smithy-checksums/src/body/validate.rs +++ b/rust-runtime/aws-smithy-checksums/src/body/validate.rs @@ -8,7 +8,7 @@ use crate::http::HttpChecksum; -use aws_smithy_http::body::SdkBody; +use aws_smithy_types::body::SdkBody; use bytes::Bytes; use http::{HeaderMap, HeaderValue}; @@ -48,7 +48,7 @@ impl ChecksumBody { fn poll_inner( self: Pin<&mut Self>, cx: &mut Context<'_>, - ) -> Poll>> { + ) -> Poll>> { use http_body::Body; let this = self.project(); @@ -126,7 +126,7 @@ impl std::error::Error for Error {} impl http_body::Body for ChecksumBody { type Data = Bytes; - type Error = aws_smithy_http::body::Error; + type Error = aws_smithy_types::body::Error; fn poll_data( self: Pin<&mut Self>, @@ -155,7 +155,7 @@ impl http_body::Body for ChecksumBody { mod tests { use crate::body::validate::{ChecksumBody, Error}; use crate::ChecksumAlgorithm; - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; use bytes::{Buf, Bytes}; use bytes_utils::SegmentedBuf; use http_body::Body; diff --git a/rust-runtime/aws-smithy-http-server-python/src/pytests/bytestream.rs b/rust-runtime/aws-smithy-http-server-python/src/pytests/bytestream.rs index 30cc997e760..c82ffb233ba 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/pytests/bytestream.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/pytests/bytestream.rs @@ -10,8 +10,8 @@ use futures_util::stream; use hyper::Body; use pyo3::{prelude::*, py_run}; -use aws_smithy_http::body::SdkBody; use aws_smithy_http_server_python::types::ByteStream; +use aws_smithy_types::body::SdkBody; #[pyo3_asyncio::tokio::test] fn consuming_stream_on_python_synchronously() -> PyResult<()> { diff --git a/rust-runtime/aws-smithy-http-server-python/src/types.rs b/rust-runtime/aws-smithy-http-server-python/src/types.rs index a274efe086d..1af75dbd27d 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/types.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/types.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -//! Python wrapped types from aws-smithy-types and aws-smithy-http. +//! Python wrapped types from aws-smithy-types. //! //! ## `Deref` hacks for Json serializer //! [aws_smithy_json::serialize::JsonValueWriter] expects references to the types @@ -301,11 +301,11 @@ impl Deref for DateTime { } } -/// Python Wrapper for [aws_smithy_http::byte_stream::ByteStream]. +/// Python Wrapper for [aws_smithy_types::byte_stream::ByteStream]. /// /// ByteStream provides misuse-resistant primitives to make it easier to handle common patterns with streaming data. /// -/// On the Rust side, The Python implementation wraps the original [ByteStream](aws_smithy_http::byte_stream::ByteStream) +/// On the Rust side, The Python implementation wraps the original [ByteStream](aws_smithy_types::byte_stream::ByteStream) /// in a clonable structure and implements the [Stream](futures::stream::Stream) trait for it to /// allow Rust to handle the type transparently. /// @@ -332,17 +332,17 @@ impl Deref for DateTime { /// effectively maintaining the asyncronous behavior that Rust exposes, while the sync one is blocking the Tokio runtime to be able /// to await one chunk at a time. /// -/// The original Rust [ByteStream](aws_smithy_http::byte_stream::ByteStream) is wrapped inside a `Arc` to allow the type to be +/// The original Rust [ByteStream](aws_smithy_types::byte_stream::ByteStream) is wrapped inside a `Arc` to allow the type to be /// [Clone] (required by PyO3) and to allow internal mutability, required to fetch the next chunk of data. /// /// :param input bytes: /// :rtype None: #[pyclass] #[derive(Debug, Clone)] -pub struct ByteStream(Arc>); +pub struct ByteStream(Arc>); impl futures::stream::Stream for ByteStream { - type Item = Result; + type Item = Result; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let stream = self.0.lock(); @@ -356,7 +356,7 @@ impl futures::stream::Stream for ByteStream { /// Return a new data chunk from the stream. async fn yield_data_chunk( - body: Arc>, + body: Arc>, ) -> PyResult> { let mut stream = body.lock().await; stream @@ -367,37 +367,37 @@ async fn yield_data_chunk( } impl ByteStream { - /// Construct a new [ByteStream](aws_smithy_http::byte_stream::ByteStream) from a - /// [SdkBody](aws_smithy_http::body::SdkBody). + /// Construct a new [`ByteStream`](aws_smithy_types::byte_stream::ByteStream) from a + /// [`SdkBody`](aws_smithy_types::body::SdkBody). /// /// This method is available only to Rust and it is required to comply with the /// interface required by the code generator. - pub fn new(body: aws_smithy_http::body::SdkBody) -> Self { + pub fn new(body: aws_smithy_types::body::SdkBody) -> Self { Self(Arc::new(Mutex::new( - aws_smithy_http::byte_stream::ByteStream::new(body), + aws_smithy_types::byte_stream::ByteStream::new(body), ))) } } impl Default for ByteStream { fn default() -> Self { - Self::new(aws_smithy_http::body::SdkBody::from("")) + Self::new(aws_smithy_types::body::SdkBody::from("")) } } #[pymethods] impl ByteStream { - /// Create a new [ByteStream](aws_smithy_http::byte_stream::ByteStream) from a slice of bytes. + /// Create a new [ByteStream](aws_smithy_types::byte_stream::ByteStream) from a slice of bytes. #[new] pub fn newpy(input: &[u8]) -> Self { Self(Arc::new(Mutex::new( - aws_smithy_http::byte_stream::ByteStream::new(aws_smithy_http::body::SdkBody::from( + aws_smithy_types::byte_stream::ByteStream::new(aws_smithy_types::body::SdkBody::from( input, )), ))) } - /// Create a new [ByteStream](aws_smithy_http::byte_stream::ByteStream) from a path, without + /// Create a new [ByteStream](aws_smithy_types::byte_stream::ByteStream) from a path, without /// requiring Python to await this method. /// /// **NOTE:** This method will block the Rust event loop when it is running. @@ -407,7 +407,7 @@ impl ByteStream { #[staticmethod] pub fn from_path_blocking(py: Python, path: String) -> PyResult> { let byte_stream = Handle::current().block_on(async { - aws_smithy_http::byte_stream::ByteStream::from_path(path) + aws_smithy_types::byte_stream::ByteStream::from_path(path) .await .map_err(|e| PyRuntimeError::new_err(e.to_string())) })?; @@ -415,7 +415,7 @@ impl ByteStream { Ok(result.into_py(py)) } - /// Create a new [ByteStream](aws_smithy_http::byte_stream::ByteStream) from a path, forcing + /// Create a new [ByteStream](aws_smithy_types::byte_stream::ByteStream) from a path, forcing /// Python to await this coroutine. /// /// :param path str: @@ -423,7 +423,7 @@ impl ByteStream { #[staticmethod] pub fn from_path(py: Python, path: String) -> PyResult<&PyAny> { pyo3_asyncio::tokio::future_into_py(py, async move { - let byte_stream = aws_smithy_http::byte_stream::ByteStream::from_path(path) + let byte_stream = aws_smithy_types::byte_stream::ByteStream::from_path(path) .await .map_err(|e| PyRuntimeError::new_err(e.to_string()))?; Ok(Self(Arc::new(Mutex::new(byte_stream)))) @@ -440,7 +440,7 @@ impl ByteStream { /// Return the next item from the iterator. If there are no further items, raise the StopIteration exception. /// PyO3 allows to raise the correct exception using the enum [IterNextOutput](pyo3::pyclass::IterNextOutput). /// - /// To get tnext value of the iterator, the `Arc` inner stream is cloned and the Rust call to `next()` is executed + /// To get the next value of the iterator, the `Arc` inner stream is cloned and the Rust call to `next()` is executed /// inside a call blocking the Tokio runtime. /// /// More info: `` diff --git a/rust-runtime/aws-smithy-http/src/body.rs b/rust-runtime/aws-smithy-http/src/body.rs new file mode 100644 index 00000000000..bd961ce383e --- /dev/null +++ b/rust-runtime/aws-smithy-http/src/body.rs @@ -0,0 +1,21 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//TODO(runtimeCratesVersioningCleanup): Re-point those who use the deprecated type aliases to +// directly depend on `aws_smithy_types` and remove this module. + +//! Types for representing the body of an HTTP request or response + +/// A boxed generic HTTP body that, when consumed, will result in [`Bytes`](bytes::Bytes) or an [`Error`](aws_smithy_types::body::Error). +#[deprecated(note = "Moved to `aws_smithy_types::body::BoxBody`.")] +pub type BoxBody = aws_smithy_types::body::BoxBody; + +/// A generic, boxed error that's `Send` and `Sync` +#[deprecated(note = "`Moved to `aws_smithy_types::body::Error`.")] +pub type Error = aws_smithy_types::body::Error; + +/// SdkBody type +#[deprecated(note = "Moved to `aws_smithy_types::body::SdkBody`.")] +pub type SdkBody = aws_smithy_types::body::SdkBody; diff --git a/rust-runtime/aws-smithy-http/src/byte_stream.rs b/rust-runtime/aws-smithy-http/src/byte_stream.rs new file mode 100644 index 00000000000..e97a395b8e7 --- /dev/null +++ b/rust-runtime/aws-smithy-http/src/byte_stream.rs @@ -0,0 +1,24 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//TODO(runtimeCratesVersioningCleanup): Re-point those who use the deprecated type aliases to +// directly depend on `aws_smithy_types` and remove this module. + +//! ByteStream Abstractions + +/// Non-contiguous Binary Data Storage +#[deprecated(note = "Moved to `aws_smithy_types::byte_stream::AggregatedBytes`.")] +pub type AggregatedBytes = aws_smithy_types::byte_stream::AggregatedBytes; + +/// Stream of binary data +#[deprecated(note = "Moved to `aws_smithy_types::byte_stream::ByteStream`.")] +pub type ByteStream = aws_smithy_types::byte_stream::ByteStream; + +/// Errors related to bytestreams. +pub mod error { + /// An error occurred in the byte stream + #[deprecated(note = "Moved to `aws_smithy_types::byte_stream::error::Error`.")] + pub type Error = aws_smithy_types::byte_stream::error::Error; +} diff --git a/rust-runtime/aws-smithy-http/src/event_stream/receiver.rs b/rust-runtime/aws-smithy-http/src/event_stream/receiver.rs index eb931900a56..eb6e7544318 100644 --- a/rust-runtime/aws-smithy-http/src/event_stream/receiver.rs +++ b/rust-runtime/aws-smithy-http/src/event_stream/receiver.rs @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -use crate::body::SdkBody; use crate::result::{ConnectorError, SdkError}; use aws_smithy_eventstream::frame::{ DecodedFrame, Message, MessageFrameDecoder, UnmarshallMessage, UnmarshalledMessage, }; +use aws_smithy_types::body::SdkBody; use bytes::Buf; use bytes::Bytes; use bytes_utils::SegmentedBuf; @@ -276,10 +276,10 @@ impl Receiver { #[cfg(test)] mod tests { use super::{Receiver, UnmarshallMessage}; - use crate::body::SdkBody; use crate::result::SdkError; use aws_smithy_eventstream::error::Error as EventStreamError; use aws_smithy_eventstream::frame::{Header, HeaderValue, Message, UnmarshalledMessage}; + use aws_smithy_types::body::SdkBody; use bytes::Bytes; use hyper::body::Body; use std::error::Error as StdError; diff --git a/rust-runtime/aws-smithy-http/src/futures_stream_adapter.rs b/rust-runtime/aws-smithy-http/src/futures_stream_adapter.rs index 65b5d5d0429..74b1adb144a 100644 --- a/rust-runtime/aws-smithy-http/src/futures_stream_adapter.rs +++ b/rust-runtime/aws-smithy-http/src/futures_stream_adapter.rs @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -use crate::body::SdkBody; -use crate::byte_stream::error::Error as ByteStreamError; -use crate::byte_stream::ByteStream; +use aws_smithy_types::body::SdkBody; +use aws_smithy_types::byte_stream::error::Error as ByteStreamError; +use aws_smithy_types::byte_stream::ByteStream; use bytes::Bytes; use futures_core::stream::Stream; use std::pin::Pin; diff --git a/rust-runtime/aws-smithy-http/src/lib.rs b/rust-runtime/aws-smithy-http/src/lib.rs index 245a477fb4c..6a77d080439 100644 --- a/rust-runtime/aws-smithy-http/src/lib.rs +++ b/rust-runtime/aws-smithy-http/src/lib.rs @@ -25,11 +25,8 @@ #![allow(clippy::derive_partial_eq_without_eq)] #![cfg_attr(docsrs, feature(doc_cfg))] -//TODO(runtimeCratesVersioningCleanup): Re-point those who use the following reexports to -// directly depend on `aws_smithy_types` and remove the reexports below. -pub use aws_smithy_types::body; -pub use aws_smithy_types::byte_stream; - +pub mod body; +pub mod byte_stream; pub mod endpoint; // Marked as `doc(hidden)` because a type in the module is used both by this crate and by the code // generator, but not by external users. Also, by the module being `doc(hidden)` instead of it being diff --git a/rust-runtime/aws-smithy-http/src/result.rs b/rust-runtime/aws-smithy-http/src/result.rs index 03119ef64f6..8ac6b1b613a 100644 --- a/rust-runtime/aws-smithy-http/src/result.rs +++ b/rust-runtime/aws-smithy-http/src/result.rs @@ -5,8 +5,8 @@ //! Types for [error](SdkError) responses. -use crate::body::SdkBody; use crate::connection::ConnectionMetadata; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::error::metadata::{ProvideErrorMetadata, EMPTY_ERROR_METADATA}; use aws_smithy_types::error::ErrorMetadata; use aws_smithy_types::retry::ErrorKind; diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/http/request.rs b/rust-runtime/aws-smithy-runtime-api/src/client/http/request.rs index caae96e18e1..8619c2841ab 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/http/request.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/http/request.rs @@ -5,7 +5,7 @@ //! Http Request Types -use aws_smithy_http::body::SdkBody; +use aws_smithy_types::body::SdkBody; use http as http0; use http::header::{InvalidHeaderName, InvalidHeaderValue}; use http::uri::InvalidUri; @@ -616,7 +616,7 @@ fn header_value(value: MaybeStatic) -> Result { #[cfg(test)] mod test { use crate::client::orchestrator::HttpRequest; - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; use http::header::{AUTHORIZATION, CONTENT_LENGTH}; use http::{HeaderValue, Uri}; diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs b/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs index 8f976903c7a..051f3ebf588 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs @@ -428,7 +428,7 @@ impl fmt::Display for RewindResult { #[cfg(all(test, feature = "test-util"))] mod tests { use super::*; - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; use http::header::{AUTHORIZATION, CONTENT_LENGTH}; use http::{HeaderValue, Uri}; diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/orchestrator.rs b/rust-runtime/aws-smithy-runtime-api/src/client/orchestrator.rs index b59a69b0c97..350c399e1ec 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/orchestrator.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/orchestrator.rs @@ -20,8 +20,8 @@ use crate::box_error::BoxError; use crate::client::interceptors::context::phase::Phase; use crate::client::interceptors::context::Error; use crate::client::interceptors::InterceptorError; -use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::{ConnectorError, SdkError}; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::{Storable, StoreReplace}; use bytes::Bytes; use std::error::Error as StdError; diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/runtime_plugin.rs b/rust-runtime/aws-smithy-runtime-api/src/client/runtime_plugin.rs index f55cfa6e1f6..bae79b74d56 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/runtime_plugin.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/runtime_plugin.rs @@ -308,7 +308,7 @@ mod tests { use crate::client::runtime_components::RuntimeComponentsBuilder; use crate::client::runtime_plugin::{Order, SharedRuntimePlugin}; use crate::shared::IntoShared; - use aws_smithy_http::body::SdkBody; + use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::ConfigBag; use http::HeaderValue; use std::borrow::Cow; diff --git a/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs b/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs index affff101d0d..3a6281373be 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs @@ -284,9 +284,9 @@ impl Sign for DigestAuthSigner { #[cfg(test)] mod tests { use super::*; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::identity::http::Login; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder; + use aws_smithy_types::body::SdkBody; #[test] fn test_api_key_signing_headers() { diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs b/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs index 541b11d6993..7bcdc13082a 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs @@ -6,7 +6,6 @@ use crate::client::http::connection_poisoning::CaptureSmithyConnection; use aws_smithy_async::future::timeout::TimedOutError; use aws_smithy_async::rt::sleep::{default_async_sleep, AsyncSleep, SharedAsyncSleep}; -use aws_smithy_http::body::SdkBody; use aws_smithy_http::connection::ConnectionMetadata; use aws_smithy_http::result::ConnectorError; use aws_smithy_runtime_api::box_error::BoxError; @@ -17,6 +16,7 @@ use aws_smithy_runtime_api::client::http::{ use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::error::display::DisplayErrorContext; use aws_smithy_types::retry::ErrorKind; use http::{Extensions, Uri}; diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/capture_request.rs b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/capture_request.rs index 06915c942eb..f694840b616 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/capture_request.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/capture_request.rs @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::http::{ HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpConnector, }; use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_types::body::SdkBody; use std::fmt::Debug; use std::sync::{Arc, Mutex}; use tokio::sync::oneshot; diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr.rs b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr.rs index 95a3b2be142..5f50faaed7d 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr.rs @@ -246,9 +246,9 @@ impl From for BodyData { #[cfg(test)] mod tests { use super::*; - use aws_smithy_http::body::SdkBody; - use aws_smithy_http::byte_stream::ByteStream; use aws_smithy_runtime_api::client::http::{HttpConnector, SharedHttpConnector}; + use aws_smithy_types::body::SdkBody; + use aws_smithy_types::byte_stream::ByteStream; use bytes::Bytes; use http::Uri; use std::error::Error; diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/record.rs b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/record.rs index 1c682ad7ede..912a409b26b 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/record.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/record.rs @@ -7,13 +7,13 @@ use super::{ Action, BodyData, ConnectionId, Direction, Error, Event, NetworkTraffic, Request, Response, Version, }; -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::http::{ HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpConnector, }; use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_types::body::SdkBody; use http_body::Body; use std::path::Path; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/replay.rs b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/replay.rs index 72c4d2d8618..d0f868a19c5 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/replay.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/dvr/replay.rs @@ -4,7 +4,6 @@ */ use super::{Action, ConnectionId, Direction, Event, NetworkTraffic}; -use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::ConnectorError; use aws_smithy_protocol_test::MediaType; use aws_smithy_runtime_api::client::http::{ @@ -13,6 +12,7 @@ use aws_smithy_runtime_api::client::http::{ use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::error::display::DisplayErrorContext; use bytes::{Bytes, BytesMut}; use http::{Request, Version}; diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/infallible.rs b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/infallible.rs index 3c4cea50653..2715b31c9e4 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/infallible.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/infallible.rs @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::ConnectorError; use aws_smithy_runtime_api::client::http::{ HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpClient, @@ -12,6 +11,7 @@ use aws_smithy_runtime_api::client::http::{ use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_types::body::SdkBody; use std::fmt; use std::sync::Arc; diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/replay.rs b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/replay.rs index 0ad6623da5f..b34e0aa0fff 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/test_util/replay.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/test_util/replay.rs @@ -116,8 +116,8 @@ impl ValidateRequest { /// # Example /// /// ```no_run -/// use aws_smithy_http::body::SdkBody; /// use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; +/// use aws_smithy_types::body::SdkBody; /// /// let http_client = StaticReplayClient::new(vec![ /// // Event that covers the first request/response diff --git a/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs b/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs index 0457f591225..8b2522bf959 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::interceptors::context::{ BeforeSerializationInterceptorContextRef, BeforeTransmitInterceptorContextMut, @@ -17,6 +16,7 @@ use aws_smithy_runtime_api::client::interceptors::{ }; use aws_smithy_runtime_api::client::orchestrator::HttpRequest; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::ConfigBag; use aws_smithy_types::error::display::DisplayErrorContext; use std::error::Error as StdError; diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs index bc0fd973cc5..ab328e53569 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs @@ -12,8 +12,6 @@ use crate::client::orchestrator::endpoints::orchestrate_endpoint; use crate::client::orchestrator::http::{log_response_body, read_body}; use crate::client::timeout::{MaybeTimeout, MaybeTimeoutConfig, TimeoutKind}; use aws_smithy_async::rt::sleep::AsyncSleep; -use aws_smithy_http::body::SdkBody; -use aws_smithy_http::byte_stream::ByteStream; use aws_smithy_http::result::SdkError; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::http::{HttpClient, HttpConnector, HttpConnectorSettings}; @@ -29,6 +27,8 @@ use aws_smithy_runtime_api::client::runtime_plugin::RuntimePlugins; use aws_smithy_runtime_api::client::ser_de::{ DeserializeResponse, SerializeRequest, SharedRequestSerializer, SharedResponseDeserializer, }; +use aws_smithy_types::body::SdkBody; +use aws_smithy_types::byte_stream::ByteStream; use aws_smithy_types::config_bag::ConfigBag; use aws_smithy_types::timeout::TimeoutConfig; use std::mem; diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/http.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/http.rs index 24baa8f414a..ca15aed5fb6 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/http.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/http.rs @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::orchestrator::{HttpResponse, SensitiveOutput}; +use aws_smithy_types::body::SdkBody; use aws_smithy_types::config_bag::ConfigBag; use bytes::{Buf, Bytes}; use http_body::Body; diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs index 4777f313a61..569b5b0b132 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs @@ -398,8 +398,8 @@ mod tests { use crate::client::http::test_util::{capture_request, ReplayEvent, StaticReplayClient}; use crate::client::retries::classifiers::HttpStatusCodeClassifier; use aws_smithy_async::rt::sleep::{SharedAsyncSleep, TokioSleep}; - use aws_smithy_http::body::SdkBody; use aws_smithy_http::result::ConnectorError; + use aws_smithy_types::body::SdkBody; use std::convert::Infallible; #[tokio::test] diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/classifiers.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/classifiers.rs index a1abd092c96..9a093687ba7 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/classifiers.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/classifiers.rs @@ -218,10 +218,10 @@ mod test { use crate::client::retries::classifiers::{ HttpStatusCodeClassifier, ModeledAsRetryableClassifier, }; - use aws_smithy_http::body::SdkBody; use aws_smithy_runtime_api::client::interceptors::context::{Error, Input, InterceptorContext}; use aws_smithy_runtime_api::client::orchestrator::OrchestratorError; use aws_smithy_runtime_api::client::retries::classifiers::{ClassifyRetry, RetryAction}; + use aws_smithy_types::body::SdkBody; use aws_smithy_types::retry::{ErrorKind, ProvideErrorKind}; use std::fmt; diff --git a/rust-runtime/aws-smithy-runtime/tests/reconnect_on_transient_error.rs b/rust-runtime/aws-smithy-runtime/tests/reconnect_on_transient_error.rs index 91cf73bdf71..9b4f4c2666e 100644 --- a/rust-runtime/aws-smithy-runtime/tests/reconnect_on_transient_error.rs +++ b/rust-runtime/aws-smithy-runtime/tests/reconnect_on_transient_error.rs @@ -13,7 +13,6 @@ use ::aws_smithy_runtime::client::retries::classifiers::{ HttpStatusCodeClassifier, TransientErrorClassifier, }; use aws_smithy_async::rt::sleep::TokioSleep; -use aws_smithy_http::body::{BoxBody, SdkBody}; use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder; use aws_smithy_runtime::client::http::test_util::wire::{ RecordedEvent, ReplayedEvent, WireMockServer, @@ -24,6 +23,7 @@ use aws_smithy_runtime::{ev, match_events}; use aws_smithy_runtime_api::client::interceptors::context::InterceptorContext; use aws_smithy_runtime_api::client::orchestrator::OrchestratorError; use aws_smithy_runtime_api::client::retries::classifiers::{ClassifyRetry, RetryAction}; +use aws_smithy_types::body::{BoxBody, SdkBody}; use aws_smithy_types::retry::{ErrorKind, ProvideErrorKind, ReconnectMode, RetryConfig}; use aws_smithy_types::timeout::TimeoutConfig; use hyper::client::Builder as HyperBuilder; From 1f7cc8e69ee1a7905c4c10aaf5720c71173684d8 Mon Sep 17 00:00:00 2001 From: david-perez Date: Fri, 20 Oct 2023 14:51:23 +0200 Subject: [PATCH 4/5] Update valid `Content-Type`s for example Python server (#2905) The service has a modeled event stream operation. It is exercised in the `event_stream_test`. ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._ --- examples/python/pokemon_service.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/python/pokemon_service.py b/examples/python/pokemon_service.py index 552d892ff32..8eb1255f877 100644 --- a/examples/python/pokemon_service.py +++ b/examples/python/pokemon_service.py @@ -176,8 +176,8 @@ def get_random_radio_stream(self) -> str: @app.middleware async def check_content_type_header(request: Request, next: Next) -> Response: content_type = request.headers.get("content-type") - if content_type == "application/json": - logging.debug("found valid `application/json` content type") + if content_type in ["application/json", "application/vnd.amazon.eventstream"]: + logging.debug("found valid `%s` content type", content_type) else: logging.warning( "invalid content type %s, dumping headers: %s", @@ -203,7 +203,7 @@ async def add_x_amzn_answer_header(request: Request, next: Next) -> Response: async def check_x_amzn_answer_header(request: Request, next: Next) -> Response: # Check that `x-amzn-answer` is 42. if request.headers.get("x-amzn-answer") != "42": - # Return an HTTP 401 Unauthorized if the content type is not JSON. + # Return an HTTP 401 Unauthorized. raise MiddlewareException("Invalid answer", 401) return await next(request) From 66a3acf5e0e1c8531301aeff346dca252080a7be Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Fri, 20 Oct 2023 10:50:59 -0400 Subject: [PATCH 5/5] Client examples that use the generic client have been added (#2799) ## Motivation and Context Example code that demonstrates the usage of pokemon-service-client. ## Description Examples have been added that show how to add middleware, configure retries, timeouts, and handle errors when calling operations on the pokemon-service. _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._ --------- Co-authored-by: Fahad Zubair --- examples/Cargo.toml | 1 + .../pokemon-service-client-usage/Cargo.toml | 37 ++++ .../pokemon-service-client-usage/README.md | 49 +++++ .../examples/client-connector.rs | 74 ++++++++ .../custom-header-using-interceptor.rs | 158 ++++++++++++++++ .../examples/custom-header.rs | 62 +++++++ .../examples/endpoint-resolver.rs | 102 +++++++++++ .../examples/handling-errors.rs | 135 ++++++++++++++ .../examples/mock-request.rs | 76 ++++++++ .../examples/response-header-interceptor.rs | 171 ++++++++++++++++++ .../examples/retry-classifier.rs | 112 ++++++++++++ .../examples/retry-customize.rs | 60 ++++++ .../examples/simple-client.rs | 53 ++++++ .../examples/timeout-config.rs | 64 +++++++ .../examples/trace-serialize.rs | 113 ++++++++++++ .../examples/use-config-bag.rs | 141 +++++++++++++++ .../pokemon-service-client-usage/src/lib.rs | 19 ++ 17 files changed, 1427 insertions(+) create mode 100644 examples/pokemon-service-client-usage/Cargo.toml create mode 100644 examples/pokemon-service-client-usage/README.md create mode 100644 examples/pokemon-service-client-usage/examples/client-connector.rs create mode 100644 examples/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs create mode 100644 examples/pokemon-service-client-usage/examples/custom-header.rs create mode 100644 examples/pokemon-service-client-usage/examples/endpoint-resolver.rs create mode 100644 examples/pokemon-service-client-usage/examples/handling-errors.rs create mode 100644 examples/pokemon-service-client-usage/examples/mock-request.rs create mode 100644 examples/pokemon-service-client-usage/examples/response-header-interceptor.rs create mode 100644 examples/pokemon-service-client-usage/examples/retry-classifier.rs create mode 100644 examples/pokemon-service-client-usage/examples/retry-customize.rs create mode 100644 examples/pokemon-service-client-usage/examples/simple-client.rs create mode 100644 examples/pokemon-service-client-usage/examples/timeout-config.rs create mode 100644 examples/pokemon-service-client-usage/examples/trace-serialize.rs create mode 100644 examples/pokemon-service-client-usage/examples/use-config-bag.rs create mode 100644 examples/pokemon-service-client-usage/src/lib.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 453eee98e42..9d38f8d778c 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,6 +7,7 @@ members = [ "pokemon-service-lambda", "pokemon-service-server-sdk", "pokemon-service-client", + "pokemon-service-client-usage", ] diff --git a/examples/pokemon-service-client-usage/Cargo.toml b/examples/pokemon-service-client-usage/Cargo.toml new file mode 100644 index 00000000000..d3be7c83b10 --- /dev/null +++ b/examples/pokemon-service-client-usage/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "pokemon-service-client-usage" +version = "0.1.0" +edition = "2021" +publish = false + +[features] + + +[dependencies] +# The generated client utilizes types defined in other crates, such as `aws_smithy_types` +# and `aws_smithy_http`. However, most of these types are re-exported by the generated client, +# eliminating the need to directly depend on the crates that provide them. In rare instances, +# you may still need to include one of these crates as a dependency. Examples that require this +# are specifically noted in comments above the corresponding dependency in this file. +pokemon-service-client = { path = "../pokemon-service-client/" } + +# Required for getting the operation name from the `Metadata`. +aws-smithy-http = { path = "../../rust-runtime/aws-smithy-http/" } + +# Required for `Storable` and `StoreReplace` in `response-header-interceptor` example. +aws-smithy-types = { path = "../../rust-runtime/aws-smithy-types/" } + +# Required for `HyperClientBuilder` in `client-connector` example. +aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime/", features=["test-util"] } + + + +hyper = { version = "0.14.25", features = ["client", "full"] } +tokio = {version = "1.26.0", features=["full"]} +tracing = "0.1.37" +tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } +rustls = "0.21.7" +hyper-rustls = "0.24.1" +http = "0.2.9" +uuid = {version="1.4.1", features = ["v4"]} +thiserror = "1.0.49" diff --git a/examples/pokemon-service-client-usage/README.md b/examples/pokemon-service-client-usage/README.md new file mode 100644 index 00000000000..f2b90eea952 --- /dev/null +++ b/examples/pokemon-service-client-usage/README.md @@ -0,0 +1,49 @@ +# smithy-rs Client Examples + +This package contains some examples on how to use the Smithy Client to communicate +with a Smithy-based service. + +## Pre-requisites + +1. Build the `pokemon-service-client` and `pokemon-service` by invoking `make` in the + [examples](https://github.com/awslabs/smithy-rs/tree/main/examples) folder. + +```console +make +``` + +2. Run the Pokemon service locally by issuing the following command from the + [examples](https://github.com/awslabs/smithy-rs/tree/main/examples) folder. This + will launch the Smithy-Rs based service on TCP port 13734. + +```console +cargo run --bin pokemon-service +``` + +## Running the examples + +You can view a list of examples by running `cargo run --example` from the +[pokemon-service-client-usage](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage) +folder. To run an example, pass its name to the `cargo run --example` command, e.g.: + +```console +cargo run --example simple-client +``` + +## List of examples + +| Rust Example | Description | +|--------------------------------|-------------------------------------------------------------------------| +| simple-client | Creates a Smithy Client and calls an operation on it. | +| endpoint-resolver | How to set a custom endpoint resolver. | +| handling-errors | How to send an input parameter to an operation, and to handle errors. | +| custom-header | How to add headers to a request. | +| custom-header-using-interceptor| How to access operation name being called in an interceptor. | +| response-header-interceptor | How to get operation name and access response before it is deserialized.| +| use-config-bag | How to use the property bag to pass data across interceptors. | +| retries-customize | Customize retry settings. | +| retries-disable | How to disable retries. | +| timeout-config | How to configure timeouts. | +| mock-request | Use a custom HttpConnector / Client to generate mock responses. | +| trace-serialize | Trace request and response as they are serialized / deserialized. | +| client-connector | Shows how to change TLS related configuration. | diff --git a/examples/pokemon-service-client-usage/examples/client-connector.rs b/examples/pokemon-service-client-usage/examples/client-connector.rs new file mode 100644 index 00000000000..61efcc0f69a --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/client-connector.rs @@ -0,0 +1,74 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to set connector settings. For example, how to set +/// trusted root certificates to use for HTTPs communication. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example client-connector`. +/// +use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder; +use hyper_rustls::ConfigBuilderExt; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + let tls_config = rustls::ClientConfig::builder() + .with_safe_defaults() + // `with_native_roots()`: Load platform trusted root certificates. + // `with_webpki_roots()`: Load Mozilla’s set of trusted roots. + .with_native_roots() + // To use client side certificates, you can use + // `.with_client_auth_cert(client_cert, client_key)` instead of `.with_no_client_auth()` + .with_no_client_auth(); + + let tls_connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config(tls_config) + // This can be changed to `.https_only()` to ensure that the client always uses HTTPs + .https_or_http() + .enable_http1() + .enable_http2() + .build(); + + // Create a hyper-based HTTP client that uses this TLS connector. + let http_client = HyperClientBuilder::new().build(tls_connector); + + // Pass the smithy connector to the Client::ConfigBuilder + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .http_client(http_client) + .build(); + + // Instantiate a client by applying the configuration. + pokemon_service_client::Client::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(?response, "Response from service") +} diff --git a/examples/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs b/examples/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs new file mode 100644 index 00000000000..b01d1fe2bb8 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs @@ -0,0 +1,158 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// In this example, a custom header `x-amzn-client-ttl-seconds` is set for all outgoing requests. +/// It serves as a demonstration of how an operation name can be retrieved and utilized within +/// the interceptor. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example custom-header-using-interceptor`. +/// +use std::{collections::HashMap, time::Duration}; + +use pokemon_service_client::config::{ConfigBag, Intercept}; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client::{ + config::{interceptors::BeforeTransmitInterceptorContextMut, RuntimeComponents}, + error::BoxError, +}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +// The `TtlHeaderInterceptor` keeps a map of operation specific value to send +// in the header for each Request. +#[derive(Debug)] +pub struct TtlHeaderInterceptor { + /// Default time-to-live for an operation. + default_ttl: hyper::http::HeaderValue, + /// Operation specific time-to-live. + operation_ttl: HashMap<&'static str, hyper::http::HeaderValue>, +} + +// Helper function to format duration as fractional seconds. +fn format_ttl_value(ttl: Duration) -> String { + format!("{:.2}", ttl.as_secs_f64()) +} + +impl TtlHeaderInterceptor { + fn new(default_ttl: Duration) -> Self { + let duration_str = format_ttl_value(default_ttl); + let default_ttl_value = hyper::http::HeaderValue::from_str(duration_str.as_str()) + .expect("could not create a header value for the default ttl"); + + Self { + default_ttl: default_ttl_value, + operation_ttl: Default::default(), + } + } + + /// Adds an operation name specific timeout value that needs to be set in the header. + fn add_operation_ttl(&mut self, operation_name: &'static str, ttl: Duration) { + let duration_str = format_ttl_value(ttl); + + self.operation_ttl.insert( + operation_name, + hyper::http::HeaderValue::from_str(duration_str.as_str()) + .expect("cannot create header value for the given ttl duration"), + ); + } +} + +/// Appends the header `x-amzn-client-ttl-seconds` using either the default time-to-live value +/// or an operation-specific value if it was set earlier using `add_operation_ttl`. +//impl aws_smithy_runtime_api::client::interceptors::Interceptor for TtlHeaderInterceptor { +impl Intercept for TtlHeaderInterceptor { + fn name(&self) -> &'static str { + "TtlHeaderInterceptor" + } + + /// Before the request is signed, add the header to the outgoing request. + fn modify_before_signing( + &self, + context: &mut BeforeTransmitInterceptorContextMut<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // Metadata in the ConfigBag has the operation name. + let metadata = cfg + .load::() + .expect("metadata should exist"); + let operation_name = metadata.name(); + + // Get operation specific or default HeaderValue to set for the header key. + let ttl = self + .operation_ttl + .get(operation_name) + .unwrap_or(&self.default_ttl); + + context + .request_mut() + .headers_mut() + .insert("x-amzn-client-ttl-seconds", ttl.clone()); + + tracing::info!("{operation_name} header set to {ttl:?}"); + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // By default set the value of all operations to 6 seconds. + const DEFAULT_TTL: Duration = Duration::from_secs(6); + + // Set up the interceptor to add an operation specific value of 3.5 seconds to be added + // for GetStorage operation. + let mut ttl_headers_interceptor = TtlHeaderInterceptor::new(DEFAULT_TTL); + ttl_headers_interceptor.add_operation_ttl("GetStorage", Duration::from_millis(3500)); + + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(ttl_headers_interceptor) + .build(); + + pokemon_service_client::Client::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response for get_server_statistics()"); + + // Call the operation `get_storage` on the Pokémon service. The `TtlHeaderInterceptor` + // interceptor will add a specific header name / value pair for this operation. + let response = client + .get_storage() + .user("ash") + .passcode("pikachu123") + .send() + .await + .expect("operation failed"); + + // Print the response received from the service. + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/custom-header.rs b/examples/pokemon-service-client-usage/examples/custom-header.rs new file mode 100644 index 00000000000..98dc20e2d5b --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/custom-header.rs @@ -0,0 +1,62 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to create a `smithy-rs` client, and call an operation with custom +/// headers in the request. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example custom-header` +/// +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .build(); + + // Apply the configuration on the client, and return that. + pokemon_service_client::Client::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .customize() + .mutate_request(|req| { + // For demonstration purposes, add a header `x-ttl-seconds` to the outgoing request. + let headers = req.headers_mut(); + headers.insert( + hyper::header::HeaderName::from_static("x-ttl-seconds"), + hyper::header::HeaderValue::from(30), + ); + }) + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/endpoint-resolver.rs b/examples/pokemon-service-client-usage/examples/endpoint-resolver.rs new file mode 100644 index 00000000000..d37479fa6cb --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/endpoint-resolver.rs @@ -0,0 +1,102 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how a custom `ResolveEndpoint` can be implemented for resolving +/// endpoint of a request. Additionally, it shows how a header can be added using the endpoint +/// builder. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example endpoint-resolver`. +/// +use pokemon_service_client::config::endpoint::{Endpoint, EndpointFuture, Params, ResolveEndpoint}; +use pokemon_service_client::primitives::{DateTime, DateTimeFormat}; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::setup_tracing_subscriber; + +use std::time::SystemTime; + +// This struct, provided as an example, constructs the URL that should be set on each request during initialization. +// It also implements the `ResolveEndpoint` trait, enabling it to be assigned as the endpoint_resolver in the `Config`. +#[derive(Debug)] +struct RegionalEndpoint { + url_to_use: String, +} + +impl RegionalEndpoint { + fn new(regional_url: &str, port: u16) -> Self { + let url_to_use = format!("{}:{}", regional_url, port); + RegionalEndpoint { url_to_use } + } +} + +impl ResolveEndpoint for RegionalEndpoint { + fn resolve_endpoint<'a>(&'a self, _params: &'a Params) -> EndpointFuture<'a> { + // Construct an endpoint using the Endpoint::Builder. Set the URL and, + // optionally, any headers to be sent with the request. For this example, + // we'll set the 'x-amz-date' header to the current date for all outgoing requests. + // `DateTime` can be used for formatting an RFC 3339 date time. + let now = SystemTime::now(); + let date_time = DateTime::from(now); + + let endpoint = Endpoint::builder() + .url(self.url_to_use.clone()) + .header( + "x-amz-date", + date_time + .fmt(DateTimeFormat::DateTimeWithOffset) + .expect("Could not create a date in UTC format"), + ) + .build(); + tracing::info!(?endpoint, "Resolving endpoint"); + EndpointFuture::ready(Ok(endpoint)) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + const DEFAULT_PORT: u16 = 13734; + + // Use the environment variable `REGIONAL_URL` for the URL. + let resolver = RegionalEndpoint::new( + std::env::var("REGIONAL_URL") + .as_deref() + .unwrap_or("http://localhost"), + DEFAULT_PORT, + ); + + let config = pokemon_service_client::Config::builder() + .endpoint_resolver(resolver) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/handling-errors.rs b/examples/pokemon-service-client-usage/examples/handling-errors.rs new file mode 100644 index 00000000000..ee1da30cbb8 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/handling-errors.rs @@ -0,0 +1,135 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// Copyright © 2023, Amazon, LLC. +/// +/// This example demonstrates how to handle service generated errors. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example handling-errors`. +/// +use pokemon_service_client::{error::SdkError, operation::get_storage::GetStorageError}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +use pokemon_service_client::Client as PokemonClient; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // The following example sends an incorrect passcode to the operation `get_storage`, + // which will return + // [StorageAccessNotAuthorized](https://github.com/awslabs/smithy-rs/blob/main/codegen-core/common-test-models/pokemon.smithy#L48) + let response_result = client + .get_storage() + .user("ash") + // Give a wrong password to generate a service error. + .passcode("pkachu123") + .send() + .await; + + // All errors are consolidated into an `SdkError` + match response_result { + Ok(response) => { + tracing::info!(?response, "Response from service") + } + Err(SdkError::ServiceError(se)) => { + // When an error response is received from the service, it is modeled + // as a `SdkError::ServiceError`. + match se.err() { + // Not authorized to access Pokémon storage. + GetStorageError::StorageAccessNotAuthorized(_) => { + tracing::error!("You do not have access to this resource."); + } + GetStorageError::ResourceNotFoundError(rnfe) => { + let message = rnfe.message(); + tracing::error!(error = %message, + "Given Pikachu does not exist on the server." + ) + } + GetStorageError::ValidationError(ve) => { + tracing::error!(error = %ve, "A required field has not been set."); + } + // An unexpected error occurred (e.g., invalid JSON returned by the service or an unknown error code). + GetStorageError::Unhandled(uh) => { + tracing::error!(error = %uh, "An unhandled error has occurred.") + } + // The SdkError is marked as `#[non_exhaustive]`. Therefore, a catch-all pattern is required to handle + // potential future variants introduced in SdkError. + _ => { + tracing::error!(error = %se.err(), "Some other error has occurred on the server") + } + } + } + Err(SdkError::TimeoutError(_)) => { + tracing::error!("The request timed out and could not be completed"); + } + Err(SdkError::ResponseError(re)) => { + // Raw response received from the service can be retrieved using + // the `raw()` method. + tracing::error!( + "An unparsable response was received. Raw response: {:?}", + re.raw() + ); + } + Err(sdk_error) => { + // To retrieve the `source()` of an error within the following match statements, + // we work with the parent `SdkError` type, as individual variants don't directly provide it. + // Converting the parent error to its source transfers ownership of the variable. + match sdk_error { + SdkError::DispatchFailure(ref failure) => { + if failure.is_io() { + tracing::error!("An I/O error occurred"); + } else if failure.is_timeout() { + tracing::error!("Request timed out"); + } else if failure.is_user() { + tracing::error!("An invalid HTTP request has been provided"); + } else { + tracing::error!("Some other dispatch error occurred."); + }; + + if let Ok(source) = sdk_error.into_source() { + tracing::error!(%source, "Error source"); + } + } + SdkError::ConstructionFailure(_) => { + if let Ok(source) = sdk_error.into_source() { + tracing::error!(%source, "Request could not be constructed."); + } else { + tracing::error!("Request could not be constructed for unknown reasons"); + } + } + _ => { + tracing::error!("An unknown error has occurred"); + } + } + } + } +} diff --git a/examples/pokemon-service-client-usage/examples/mock-request.rs b/examples/pokemon-service-client-usage/examples/mock-request.rs new file mode 100644 index 00000000000..64f21beb658 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/mock-request.rs @@ -0,0 +1,76 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to use a mock connector with `capture_request`. This allows for +/// responding with a static `Response` while capturing the incoming request. The captured request +/// can later be asserted to verify that the correct headers and body were sent to the server. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example mock-request`. +/// +use aws_smithy_runtime::client::http::test_util::capture_request; +use aws_smithy_types::body::SdkBody; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Build a response that should be sent when the operation is called. + let response = http::Response::builder() + .status(200) + .body(SdkBody::from(r#"{"calls_count":100}"#)) + .expect("response could not be constructed"); + + // Call `capture_request` to obtain a HTTP connector and a request receiver. + // The request receiver captures the incoming request, while the connector can be passed + // to `Config::builder().http_client`. + let (http_client, captured_request) = capture_request(Some(response)); + + // Pass the `http_client` connector to `Config::builder`. The connector won't send + // the request over the network; instead, it will return the static response provided + // during its initialization. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .http_client(http_client) + .build(); + + // Instantiate a client by applying the configuration. + let client = PokemonClient::from_conf(config); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .customize() + .mutate_request(|req| { + // For demonstration, send an extra header that can be verified to confirm + // that the client actually sends it. + let headers = req.headers_mut(); + headers.insert( + hyper::header::HeaderName::from_static("user-agent"), + hyper::header::HeaderName::from_static("sample-client"), + ); + }) + .send() + .await + .expect("operation failed"); + + // Print the response received from the service. + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); + + // The captured request can be verified to have certain headers. + let req = captured_request.expect_request(); + assert_eq!(req.headers().get("user-agent"), Some("sample-client")); + + // As an example, you can verify the URL matches. + assert_eq!(req.uri(), "http://localhost:13734/stats"); + + // You can convert the captured body into a &str and use assert! + // on it if you want to verify the contents of the request body. + // let str_body = std::str::from_utf8(req.body().bytes().unwrap()).unwrap(); +} diff --git a/examples/pokemon-service-client-usage/examples/response-header-interceptor.rs b/examples/pokemon-service-client-usage/examples/response-header-interceptor.rs new file mode 100644 index 00000000000..14928fe28c1 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/response-header-interceptor.rs @@ -0,0 +1,171 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how response headers can be examined before they are deserialized +/// into the output type. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example response-header-interceptor`. +/// +//use aws_smithy_types::config_bag::{Storable, StoreReplace}; +use aws_smithy_types::config_bag::{Storable, StoreReplace}; +use pokemon_service_client::{ + config::{ + interceptors::{ + BeforeDeserializationInterceptorContextRef, BeforeTransmitInterceptorContextMut, + }, + ConfigBag, Intercept, RuntimeComponents, + }, + error::BoxError, + Client as PokemonClient, +}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use uuid::Uuid; + +#[derive(Debug, Clone)] +struct RequestId { + client_id: String, + server_id: Option, +} + +impl Storable for RequestId { + type Storer = StoreReplace; +} + +#[derive(Debug, thiserror::Error)] +enum RequestIdError { + /// The server-sent request ID cannot be converted into a string during parsing. + #[error("RequestID sent by the server cannot be parsed into a string. Error: {0}")] + NonParsableServerRequestId(String), + /// Client side + #[error("Client side request ID has not been set")] + ClientRequestIdMissing(), +} + +#[derive(Debug, Default)] +pub struct ResponseHeaderLoggingInterceptor; + +impl ResponseHeaderLoggingInterceptor { + /// Creates a new `ResponseHeaderLoggingInterceptor` + pub fn new() -> Self { + Self::default() + } +} + +impl Intercept for ResponseHeaderLoggingInterceptor { + fn name(&self) -> &'static str { + "ResponseHeaderLoggingInterceptor" + } + + /// Before the request is signed, add the header to the outgoing request. + fn modify_before_signing( + &self, + context: &mut BeforeTransmitInterceptorContextMut<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + let client_id = Uuid::new_v4().to_string(); + + let request_id = hyper::header::HeaderValue::from_str(&client_id) + .expect("failed to construct a header value from UUID"); + context + .request_mut() + .headers_mut() + .insert("x-amzn-requestid", request_id); + + cfg.interceptor_state().store_put(RequestId { + client_id, + server_id: None, + }); + + Ok(()) + } + + fn read_before_deserialization( + &self, + context: &BeforeDeserializationInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // `Metadata` in the `ConfigBag` has the operation name in it. + let metadata = cfg + .load::() + .expect("metadata should exist"); + let operation_name = metadata.name().to_string(); + + // Get the server side request ID and set it in the RequestID data type + // that is in the ConfigBag. This way any other interceptor that requires the mapping + // can easily find it from the bag. + let response = context.response(); + let header_received = response + .headers() + .iter() + .find(|(header_name, _)| *header_name == "x-request-id"); + + if let Some((_, server_id)) = header_received { + let server_id = server_id + .to_str() + .map_err(|e| Box::new(RequestIdError::NonParsableServerRequestId(e.to_string())))?; + + let request_details = cfg + .get_mut::() + .ok_or_else(|| Box::new(RequestIdError::ClientRequestIdMissing()))?; + + tracing::info!(operation = %operation_name, + "RequestID Mapping: {} = {server_id}", + request_details.client_id, + ); + + request_details.server_id = Some(server_id.into()); + } else { + tracing::info!(operation = %operation_name, "Server RequestID missing in response"); + } + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(ResponseHeaderLoggingInterceptor) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + // If you need to access the `RequestIdError` raised by the interceptor, + // you can convert `SdkError::DispatchFailure` to a `ConnectorError` + // and then use `downcast_ref` on its source to get a `RequestIdError`. + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/retry-classifier.rs b/examples/pokemon-service-client-usage/examples/retry-classifier.rs new file mode 100644 index 00000000000..7ff17f0e668 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/retry-classifier.rs @@ -0,0 +1,112 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how a custom RetryClassifier can be written to decide +/// which error conditions should be retried. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example retry-classifier`. +/// +use http::StatusCode; +use pokemon_service_client::{ + config::{ + interceptors::InterceptorContext, + retry::{ClassifyRetry, RetryAction, RetryConfig}, + }, + operation::get_server_statistics::GetServerStatisticsError, +}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::time::Duration; + +use pokemon_service_client::Client as PokemonClient; + +#[derive(Debug)] +struct SampleRetryClassifier; + +// By default, the generated client uses the `aws_http::retry::AwsResponseRetryClassifier` +// to determine whether an error should be retried. To use a custom retry classifier, +// implement the `ClassifyRetry` trait and pass it to the retry_classifier method +// of the `Config::builder`. +impl ClassifyRetry for SampleRetryClassifier { + fn name(&self) -> &'static str { + "SampleRetryClassifier" + } + + // For this example, the classifier should retry in case the error is GetServerStatisticsError + // and the status code is 503. + fn classify_retry(&self, ctx: &InterceptorContext) -> RetryAction { + // Get the output or error that has been deserialized from the response. + let output_or_error = ctx.output_or_error(); + + let error = match output_or_error { + Some(Ok(_)) | None => return RetryAction::NoActionIndicated, + Some(Err(err)) => err, + }; + + // Retry in case the error returned is GetServerStatisticsError and StatusCode is 503. + if let Some(_err) = error + .as_operation_error() + .and_then(|err| err.downcast_ref::()) + { + if let Some(response) = ctx.response() { + if response.status() == StatusCode::SERVICE_UNAVAILABLE { + return RetryAction::server_error(); + } + } + } + + // Let other classifiers run and decide if the request should be retried. + // Returning RetryAction::RetryForbidden will forbid any retries. + RetryAction::NoActionIndicated + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // By default the Smithy client uses RetryConfig::standard() strategy, with 3 retries, and + // an initial exponential back off of 1 second. To turn it off use RetryConfig::disabled(). + let retry_config = RetryConfig::standard() + .with_initial_backoff(Duration::from_secs(3)) + .with_max_attempts(5); + + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .retry_config(retry_config) + // Add the retry classifier. + .retry_classifier(SampleRetryClassifier {}) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/retry-customize.rs b/examples/pokemon-service-client-usage/examples/retry-customize.rs new file mode 100644 index 00000000000..5deb3af0ffa --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/retry-customize.rs @@ -0,0 +1,60 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to customize retry settings on a Smithy client. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example retry-customize`. +/// +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::time::Duration; + +use pokemon_service_client::{config::retry::RetryConfig, Client as PokemonClient}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // By default the Smithy client uses `RetryConfig::standard()` strategy, with 3 retries, and + // an initial exponential back off of 1 second. To turn it off use `RetryConfig::disabled()`. + let retry_config = RetryConfig::standard() + .with_initial_backoff(Duration::from_secs(3)) + .with_max_attempts(5); + + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .retry_config(retry_config) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/simple-client.rs b/examples/pokemon-service-client-usage/examples/simple-client.rs new file mode 100644 index 00000000000..e04e2345e82 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/simple-client.rs @@ -0,0 +1,53 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to create a `smithy-rs` Client and call an +/// [operation](https://smithy.io/2.0/spec/idl.html?highlight=operation#operation-shape). +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example simple-client`. +/// +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client contains a type `config::Builder` for constructing a `Config` instance. + // This enables configuration of endpoint resolvers, timeouts, retries, etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .build(); + + // Instantiate a client by applying the configuration. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + // Print the response received from the service. + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/timeout-config.rs b/examples/pokemon-service-client-usage/examples/timeout-config.rs new file mode 100644 index 00000000000..cbfbb8e7e45 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/timeout-config.rs @@ -0,0 +1,64 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to create a `smithy-rs` Client and set connection +/// and operation related timeouts on the client. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example timeout-config` +/// +use std::time::Duration; + +use pokemon_service_client::{config::timeout::TimeoutConfig, Client as PokemonClient}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // Different type of timeouts can be set on the client. These are: + // operation_attempt_timeout - If retries are enabled, this represents the timeout + // for each individual operation attempt. + // operation_timeout - Overall timeout for the operation to complete. + // connect timeout - The amount of time allowed for a connection to be established. + let timeout_config = TimeoutConfig::builder() + .operation_attempt_timeout(Duration::from_secs(1)) + .operation_timeout(Duration::from_secs(5)) + .connect_timeout(Duration::from_millis(500)) + .build(); + + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .timeout_config(timeout_config) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("Pokemon service does not seem to be running on localhost:13734"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/trace-serialize.rs b/examples/pokemon-service-client-usage/examples/trace-serialize.rs new file mode 100644 index 00000000000..7826679e2ed --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/trace-serialize.rs @@ -0,0 +1,113 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how an interceptor can be written to trace what is being +/// serialized / deserialized on the wire. +/// +/// Please beware that this may log sensitive information! This example is meant for pedagogical +/// purposes and may be useful in debugging scenarios. Please don't use this as-is in production. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example trace-serialize`. +/// +use http::StatusCode; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::str; + +use pokemon_service_client::{ + config::{ + interceptors::{ + BeforeDeserializationInterceptorContextRef, BeforeTransmitInterceptorContextRef, + }, + ConfigBag, Intercept, RuntimeComponents, + }, + error::BoxError, + Client as PokemonClient, +}; + +/// An example interceptor that logs the request and response as they're sent and received. +#[derive(Debug, Default)] +pub struct WireFormatInterceptor; + +impl Intercept for WireFormatInterceptor { + fn name(&self) -> &'static str { + "WireFormatInterceptor" + } + + // Called after the operation input has been serialized but before it's dispatched over the wire. + fn read_after_serialization( + &self, + context: &BeforeTransmitInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + _cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // Get the request type from the context. + let request = context.request(); + // Print the request to the debug tracing log. + tracing::debug!(?request); + + Ok(()) + } + + // Called after the operation's response has been received but before it's deserialized into the + // operation's output type. + fn read_before_deserialization( + &self, + context: &BeforeDeserializationInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + _cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // Get the response type from the context. + let response = context.response(); + // Print the response. + if response.status() == StatusCode::OK { + tracing::info!(?response, "Response received:"); + } else { + tracing::error!(?response); + } + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(WireFormatInterceptor {}) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/examples/use-config-bag.rs b/examples/pokemon-service-client-usage/examples/use-config-bag.rs new file mode 100644 index 00000000000..6dd9cba3a50 --- /dev/null +++ b/examples/pokemon-service-client-usage/examples/use-config-bag.rs @@ -0,0 +1,141 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how different interceptor can use a property bag to pass +/// state from one interceptor to the next. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/awslabs/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example use-config-bag`. +/// +//use aws_smithy_types::config_bag::{Storable, StoreReplace}; +use aws_smithy_types::config_bag::{Storable, StoreReplace}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::time::Instant; + +use pokemon_service_client::{ + config::{ + interceptors::{ + BeforeDeserializationInterceptorContextRef, FinalizerInterceptorContextRef, + }, + ConfigBag, Intercept, RuntimeComponents, + }, + error::BoxError, + Client as PokemonClient, +}; + +#[derive(Debug)] +struct RequestTimestamp(Instant); + +impl Storable for RequestTimestamp { + type Storer = StoreReplace; +} + +#[derive(Debug, Default)] +pub struct SetTimeInterceptor; + +/// Note: This is merely an example demonstrating how state can +/// be shared between two different interceptors. In a practical +/// scenario, there wouldn't be a need to write two interceptors +/// merely to display the duration from the start of the lifecycle +/// to the receipt of the response. This task can be accomplished +/// within a single interceptor by overriding both +/// read_before_execution and read_before_deserialization. +impl Intercept for SetTimeInterceptor { + fn name(&self) -> &'static str { + "SetTimeInterceptor" + } + + fn read_before_execution( + &self, + _context: &pokemon_service_client::config::interceptors::BeforeSerializationInterceptorContextRef<'_>, + cfg: &mut aws_smithy_types::config_bag::ConfigBag, + ) -> Result<(), pokemon_service_client::error::BoxError> { + cfg.interceptor_state() + .store_put(RequestTimestamp(Instant::now())); + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct GetTimeInterceptor; + +impl Intercept for GetTimeInterceptor { + fn name(&self) -> &'static str { + "GetTimeInterceptor" + } + + fn read_before_deserialization( + &self, + _context: &BeforeDeserializationInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + let stop_watch = cfg + .load::() + .expect("StopWatch not found in the ConfigBag"); + + let time_taken = stop_watch.0.elapsed(); + tracing::info!(time_taken = %time_taken.as_micros(), "Microseconds:"); + + Ok(()) + } + + fn read_after_execution( + &self, + _context: &FinalizerInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), pokemon_service_client::error::BoxError> { + let timestamp = cfg + .load::() + .expect("RequestTimeStamp not found in the ConfigBag"); + + let time_taken = timestamp.0.elapsed(); + tracing::info!(time_taken = %time_taken.as_micros(), "Microseconds:"); + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(SetTimeInterceptor) + .interceptor(GetTimeInterceptor) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("Pokemon service does not seem to be running on localhost:13734"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/pokemon-service-client-usage/src/lib.rs b/examples/pokemon-service-client-usage/src/lib.rs new file mode 100644 index 00000000000..6612ddb4c4c --- /dev/null +++ b/examples/pokemon-service-client-usage/src/lib.rs @@ -0,0 +1,19 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +pub static POKEMON_SERVICE_URL: &str = "http://localhost:13734"; + +/// Sets up the tracing subscriber to print `tracing::info!` and `tracing::error!` messages on the console. +pub fn setup_tracing_subscriber() { + // Add a tracing subscriber that uses the environment variable RUST_LOG + // to figure out which log level should be emitted. By default use `tracing::info!` + // as the logging level. + let filter = tracing_subscriber::EnvFilter::builder() + .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into()) + .from_env_lossy(); + + tracing_subscriber::fmt::fmt() + .with_env_filter(filter) + .init(); +}