diff --git a/CHANGELOG.md b/CHANGELOG.md
index 29e53ee59e947029bbf407a92a09af771a5e25a4..fc57df15bfa042308deb9a3cf73bde02e3118dbb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@ vNext (Month Day, Year)
=======================
**New this week**
- Fix typos in module documentation for generated crates (smithy-rs#920)
+- Avoid serializing repetitive `xmlns` attributes in generated XML serializers. (aws-sdk-rust#301, smithy-rs#892)
**Breaking changes**
@@ -15,6 +16,7 @@ v0.31.0 (December 2nd, 2021)
**New this week**
- Add docs.rs metadata section to all crates to document all features
+
v0.30.0-alpha (November 23rd, 2021)
===================================
diff --git a/aws/SDK_CHANGELOG.md b/aws/SDK_CHANGELOG.md
index 33d1bdcbfe96b6df4b818ea8b0e6b971403d6ecd..87edcbe9b911748e6a4ef845a725f2e462e71067 100644
--- a/aws/SDK_CHANGELOG.md
+++ b/aws/SDK_CHANGELOG.md
@@ -2,6 +2,8 @@ vNext (Month Day, Year)
=======================
**New this release**
- Fix typos in module documentation for generated crates (smithy-rs#920)
+- Avoid serializing repetitive `xmlns` attributes in generated XML serializers. This reduces the length of serialized requests and should improve compatibility with localstack. (aws-sdk-rust#301, smithy-rs#892)
+
v0.2.0 (December 2nd, 2021)
===========================
diff --git a/aws/sdk/aws-models/s3-tests.smithy b/aws/sdk/aws-models/s3-tests.smithy
index 93b90ef34e7f6b834ba30590b7e06a39d0d4b441..60368d0604388cd4d0d441ba3183e9fb76ab95f8 100644
--- a/aws/sdk/aws-models/s3-tests.smithy
+++ b/aws/sdk/aws-models/s3-tests.smithy
@@ -111,17 +111,17 @@ apply PutBucketLifecycleConfiguration @httpRequestTests([
headers: {
// we can assert this, but when this test is promoted, it can't assert
// on the exact contents
- "content-md5": "sUu+uAZPkTtAxJdaA+9uSg==",
+ "content-md5": "JP8DTuCSH6yDC8wNGg4+mA==",
},
bodyMediaType: "application/xml",
body: """
-
-
- 1
+
+
+ 1
- Expire
- Enabled
+ Expire
+ Enabled
""",
diff --git a/aws/sdk/integration-tests/s3/Cargo.toml b/aws/sdk/integration-tests/s3/Cargo.toml
index 73c99df8a750b0d61c8b85d7b2df82d5470ecccf..f0e0b12df8761d055f8c23cb976e9e66a6055e6b 100644
--- a/aws/sdk/integration-tests/s3/Cargo.toml
+++ b/aws/sdk/integration-tests/s3/Cargo.toml
@@ -15,6 +15,7 @@ aws-smithy-async = { path = "../../build/aws-sdk/sdk/aws-smithy-async" }
aws-smithy-client = { path = "../../build/aws-sdk/sdk/aws-smithy-client", features = ["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-smithy-protocol-test = { path = "../../build/aws-sdk/sdk/aws-smithy-protocol-test" }
bytes = "1"
http = "0.2.3"
serde_json = "1"
diff --git a/aws/sdk/integration-tests/s3/tests/select-object-content.json b/aws/sdk/integration-tests/s3/tests/select-object-content.json
index 9434df269b5d532fcd7161a6e9c69a1779aeae61..481b120d4ddfa10b2278cd03bf384c2d6f523e17 100644
--- a/aws/sdk/integration-tests/s3/tests/select-object-content.json
+++ b/aws/sdk/integration-tests/s3/tests/select-object-content.json
@@ -7,25 +7,25 @@
"uri": "https://s3.us-east-2.amazonaws.com/aws-rust-sdk/sample_data.csv?select&select-type=2&x-id=SelectObjectContent",
"headers": {
"x-amz-date": [
- "20210831T010050Z"
+ "20211126T205841Z"
+ ],
+ "x-amz-content-sha256": [
+ "591d6c5a9bb1019b499d65fb01a6e473346ad65f2b513f03e17e388b3c788f53"
],
"content-type": [
"application/xml"
],
- "x-amz-content-sha256": [
- "3e2ed0bf97f28640f16193df06b497374232511cd2112b48985a306d40fb16d3"
+ "user-agent": [
+ "aws-sdk-rust/0.0.26-alpha os/macos lang/rust/1.53.0"
],
- "content-length": [
- "799"
+ "x-amz-user-agent": [
+ "aws-sdk-rust/0.0.26-alpha api/s3/0.0.26-alpha os/macos lang/rust/1.53.0"
],
"authorization": [
- "AWS4-HMAC-SHA256 Credential=test/test/us-east-2/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-user-agent, Signature=test"
+ "AWS4-HMAC-SHA256 Credential=test/20211126/us-east-2/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-user-agent, Signature=c7fd94cc4ec7b902c0d606919a350927c0cdcd625e7a0135c4bfa213dcedd4c1"
],
- "user-agent": [
- "aws-sdk-rust/0.1.0 os/linux lang/rust/1.52.1"
- ],
- "x-amz-user-agent": [
- "aws-sdk-rust/0.1.0 api/s3/0.0.16-alpha os/linux lang/rust/1.52.1"
+ "content-length": [
+ "415"
]
},
"method": "POST"
@@ -38,7 +38,7 @@
"action": {
"Data": {
"data": {
- "Utf8": "SELECT * FROM s3object s WHERE s."Name" = 'Jane'SQLUSENONE"
+ "Utf8": "SELECT * FROM s3object s WHERE s."Name" = 'Jane'SQLUSENONE"
},
"direction": "Request"
}
@@ -62,20 +62,20 @@
"status": 200,
"version": "HTTP/1.1",
"headers": {
- "x-amz-request-id": [
- "NVKMNP55BP15194G"
+ "server": [
+ "AmazonS3"
],
"x-amz-id-2": [
"geaWcKlzoJpu+EJLNG+t9uaD/9EOuQzGqcxL41SguR9xoDOVMFnjw7CFLm/yHQc3AVpHqHCo3a0="
],
+ "date": [
+ "Tue, 31 Aug 2021 01:00:52 GMT"
+ ],
"transfer-encoding": [
"chunked"
],
- "server": [
- "AmazonS3"
- ],
- "date": [
- "Tue, 31 Aug 2021 01:00:52 GMT"
+ "x-amz-request-id": [
+ "NVKMNP55BP15194G"
]
}
}
diff --git a/aws/sdk/integration-tests/s3/tests/select-object-content.rs b/aws/sdk/integration-tests/s3/tests/select-object-content.rs
index e754b5011ecf20c6ce01f989f604d3bc61ef69a9..a034830a5606ed749227350e135b3520310d264d 100644
--- a/aws/sdk/integration-tests/s3/tests/select-object-content.rs
+++ b/aws/sdk/integration-tests/s3/tests/select-object-content.rs
@@ -9,6 +9,7 @@ use aws_sdk_s3::model::{
};
use aws_sdk_s3::{Client, Config, Credentials, Region};
use aws_smithy_client::dvr::{Event, ReplayingConnection};
+use aws_smithy_protocol_test::{assert_ok, validate_body, MediaType};
use std::error::Error as StdError;
#[tokio::test]
@@ -82,14 +83,14 @@ async fn test_success() {
// Validate the requests
replayer
- .validate(&["content-type", "content-length"], validate_body)
+ .validate(&["content-type", "content-length"], body_validator)
.await
.unwrap();
}
-fn validate_body(expected_body: &[u8], actual_body: &[u8]) -> Result<(), Box> {
+fn body_validator(expected_body: &[u8], actual_body: &[u8]) -> Result<(), Box> {
let expected = std::str::from_utf8(expected_body).unwrap();
let actual = std::str::from_utf8(actual_body).unwrap();
- assert_eq!(expected, actual);
+ assert_ok(validate_body(actual, expected, MediaType::Xml));
Ok(())
}
diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt
index 198797415923e4436e5ed1aa9b6e6ef5799409f4..d285c24664c5b02a30f00eb97f70a8e69077fec0 100644
--- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt
+++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt
@@ -43,6 +43,7 @@ import software.amazon.smithy.rust.codegen.smithy.generators.UnionGenerator
import software.amazon.smithy.rust.codegen.smithy.generators.renderUnknownVariant
import software.amazon.smithy.rust.codegen.smithy.generators.serializationError
import software.amazon.smithy.rust.codegen.smithy.isOptional
+import software.amazon.smithy.rust.codegen.smithy.letIf
import software.amazon.smithy.rust.codegen.smithy.protocols.HttpBindingResolver
import software.amazon.smithy.rust.codegen.smithy.protocols.HttpLocation
import software.amazon.smithy.rust.codegen.smithy.protocols.XmlMemberIndex
@@ -123,7 +124,7 @@ class XmlBindingTraitSerializerGenerator(
"""
let mut writer = #{XmlWriter}::new(&mut out);
##[allow(unused_mut)]
- let mut root = writer.start_el(${operationXmlName.dq()})${inputShape.xmlNamespace().apply()};
+ let mut root = writer.start_el(${operationXmlName.dq()})${inputShape.xmlNamespace(root = true).apply()};
""",
*codegenScope
)
@@ -156,7 +157,7 @@ class XmlBindingTraitSerializerGenerator(
let mut writer = #{XmlWriter}::new(&mut out);
##[allow(unused_mut)]
let mut root = writer.start_el(${xmlIndex.payloadShapeName(member).dq()})${
- target.xmlNamespace().apply()
+ target.xmlNamespace(root = true).apply()
};
""",
*codegenScope
@@ -255,7 +256,7 @@ class XmlBindingTraitSerializerGenerator(
private fun RustWriter.serializeMember(memberShape: MemberShape, ctx: Ctx.Scope, rootNameOverride: String? = null) {
val target = model.expectShape(memberShape.target)
val xmlName = rootNameOverride ?: xmlIndex.memberName(memberShape)
- val ns = memberShape.xmlNamespace().apply()
+ val ns = memberShape.xmlNamespace(root = false).apply()
handleOptional(memberShape, ctx) { ctx ->
when (target) {
is StringShape, is BooleanShape, is NumberShape, is TimestampShape, is BlobShape -> {
@@ -411,7 +412,7 @@ class XmlBindingTraitSerializerGenerator(
private fun OperationShape.operationXmlMembers(): XmlMemberIndex =
XmlMemberIndex.fromMembers(httpBindingResolver.requestMembers(this, HttpLocation.DOCUMENT))
- private fun Shape.xmlNamespace(): XmlNamespaceTrait? {
- return this.getTrait() ?: rootNamespace
+ private fun Shape.xmlNamespace(root: Boolean): XmlNamespaceTrait? {
+ return this.getTrait().letIf(root) { it ?: rootNamespace }
}
}