From e6f07da7ba8589a4b7eabde494ff3fa59706225d Mon Sep 17 00:00:00 2001 From: yibole Date: Mon, 11 Nov 2024 13:19:28 -0800 Subject: [PATCH 1/4] Added hasAWSQueryCompatible field to the marshaller to determine if add "x-amzn-query-mode" to http header --- .../json/BaseAwsJsonProtocolFactory.java | 1 + .../marshall/JsonProtocolMarshaller.java | 9 +- .../JsonProtocolMarshallerBuilder.java | 12 +- .../protocols/json/AWSQueryModeTest.java | 154 ++++++++++++++++++ 4 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java diff --git a/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/BaseAwsJsonProtocolFactory.java b/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/BaseAwsJsonProtocolFactory.java index 8453a0f646ec..1f77ba1246e6 100644 --- a/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/BaseAwsJsonProtocolFactory.java +++ b/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/BaseAwsJsonProtocolFactory.java @@ -236,6 +236,7 @@ public final ProtocolMarshaller createProtocolMarshaller(Ope .operationInfo(operationInfo) .sendExplicitNullForPayload(false) .protocolMetadata(protocolMetadata) + .hasAwsQueryCompatible(hasAwsQueryCompatible) .build(); } diff --git a/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshaller.java b/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshaller.java index 04ef0c286eca..847a568c5fcd 100644 --- a/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshaller.java +++ b/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshaller.java @@ -72,12 +72,14 @@ public class JsonProtocolMarshaller implements ProtocolMarshaller build() { jsonGenerator, contentType, operationInfo, - protocolMetadata); + protocolMetadata, + hasAwsQueryCompatible); return sendExplicitNullForPayload ? protocolMarshaller : new NullAsEmptyBodyProtocolRequestMarshaller(protocolMarshaller); } diff --git a/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java new file mode 100644 index 000000000000..8b4bd78e114d --- /dev/null +++ b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java @@ -0,0 +1,154 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.protocols.json; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import org.junit.jupiter.api.Test; +import org.mockito.internal.matchers.Null; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.SdkPojo; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +//import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshaller; +import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshallerBuilder; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; + + +public class AWSQueryModeTest { + + private static final SdkClientConfiguration EMPTY_CLIENT_CONFIGURATION = SdkClientConfiguration.builder() + .build(); + private static final OperationInfo EMPTY_OPERATION_INFO = OperationInfo.builder() + .httpMethod(SdkHttpMethod.POST) + .hasImplicitPayloadMembers(true) + .build(); + + private final BaseAwsJsonProtocolFactory factory = AwsJsonProtocolFactory.builder() + .protocol(AwsJsonProtocol.AWS_JSON) + .clientConfiguration(EMPTY_CLIENT_CONFIGURATION) + .build(); + + private final Supplier structuredJsonFactory = getStructuredJsonFactory(factory); + + private final AwsJsonProtocolMetadata metadata = AwsJsonProtocolMetadata.builder() + .protocol(AwsJsonProtocol.AWS_JSON) + .contentType("application/json") + .build(); + + + static Supplier getStructuredJsonFactory(BaseAwsJsonProtocolFactory factory) { + return () -> { + try { + Method method = BaseAwsJsonProtocolFactory.class.getDeclaredMethod("getSdkFactory"); + method.setAccessible(true); + return (StructuredJsonFactory) method.invoke(factory); + } catch (Exception e) { + throw new RuntimeException(e); + } + }; + } + + + /* + * A simple test POJO to marshall + */ + private static final class TestPojo implements SdkPojo { + + private TestPojo() {} + + @Override + public List> sdkFields() { + return Collections.emptyList(); + } + + @Override + public boolean equalsBySdkFields(Object other) { + if (!(other instanceof TestPojo)) { + return false; + } + return true; + } + + @Override + public Map> sdkFieldNameToField() { + return Collections.emptyMap(); + } + + } + + @Test + public void testMarshallWithAwsQueryCompatibleTrue() { + try { + ProtocolMarshaller marshaller = + JsonProtocolMarshallerBuilder.create() + .endpoint(new URI("http://localhost/")) + .jsonGenerator(structuredJsonFactory.get().createWriter("application/json")) + .contentType("application/json") + .operationInfo(EMPTY_OPERATION_INFO) + .sendExplicitNullForPayload(false) + .protocolMetadata(metadata) + .hasAwsQueryCompatible(true) + .build(); + SdkPojo testPojo = new TestPojo(); + + SdkHttpFullRequest result = marshaller.marshall(testPojo); + + assertThat(result.headers()).containsKey("x-amzn-query-mode"); + assertThat(result.headers().get("x-amzn-query-mode").get(0)).isEqualTo("true"); + + }catch (URISyntaxException e) { + throw new RuntimeException(e); + } + + } + + @Test + public void testMarshallWithNoAwsQueryCompatible() { + try { + ProtocolMarshaller marshaller = + JsonProtocolMarshallerBuilder.create() + .endpoint(new URI("http://localhost/")) + .jsonGenerator(structuredJsonFactory.get().createWriter("application/json")) + .contentType("application/json") + .operationInfo(EMPTY_OPERATION_INFO) + .sendExplicitNullForPayload(false) + .protocolMetadata(metadata) + .build(); + SdkPojo testPojo = new TestPojo(); + + SdkHttpFullRequest result = marshaller.marshall(testPojo); + + assertThat(result.headers()).doesNotContainKey("x-amzn-query-mode"); + + }catch (URISyntaxException e) { + throw new RuntimeException(e); + } + + } + +} From 2634caf61c16e47b6bdd4ccd7bbffe82d53c8c0a Mon Sep 17 00:00:00 2001 From: yibole Date: Mon, 11 Nov 2024 15:51:12 -0800 Subject: [PATCH 2/4] lines adjusted --- .../amazon/awssdk/protocols/json/AWSQueryModeTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java index 8b4bd78e114d..5a292388fa07 100644 --- a/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java +++ b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java @@ -15,7 +15,6 @@ package software.amazon.awssdk.protocols.json; -import java.io.IOException; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; @@ -24,7 +23,6 @@ import java.util.Map; import java.util.function.Supplier; import org.junit.jupiter.api.Test; -import org.mockito.internal.matchers.Null; import software.amazon.awssdk.core.SdkField; import software.amazon.awssdk.core.SdkPojo; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -32,12 +30,8 @@ import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.protocols.core.OperationInfo; import software.amazon.awssdk.protocols.core.ProtocolMarshaller; -//import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshaller; import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshallerBuilder; - import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertTrue; - public class AWSQueryModeTest { From 3ff50118eaf77e91ee3199d0bf6a3aae67834036 Mon Sep 17 00:00:00 2001 From: yibole Date: Tue, 12 Nov 2024 12:45:06 -0800 Subject: [PATCH 3/4] test case adjusted to also test BaseAwsJsonProtocolFactory --- .../JsonProtocolMarshallerBuilder.java | 2 +- .../protocols/json/AWSQueryModeTest.java | 111 +++++++----------- 2 files changed, 41 insertions(+), 72 deletions(-) diff --git a/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshallerBuilder.java b/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshallerBuilder.java index 69e1149660d3..6e6a83d7f598 100644 --- a/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshallerBuilder.java +++ b/core/protocols/aws-json-protocol/src/main/java/software/amazon/awssdk/protocols/json/internal/marshall/JsonProtocolMarshallerBuilder.java @@ -104,7 +104,7 @@ public JsonProtocolMarshallerBuilder protocolMetadata(AwsJsonProtocolMetadata pr } /** - * @param hasAwsQueryCompatible + * @param hasAwsQueryCompatible True if the service is AWS Query compatible, (has the @awsQueryCompatible trait) */ public JsonProtocolMarshallerBuilder hasAwsQueryCompatible(boolean hasAwsQueryCompatible) { this.hasAwsQueryCompatible = hasAwsQueryCompatible; diff --git a/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java index 5a292388fa07..0e77866839a2 100644 --- a/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java +++ b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java @@ -23,51 +23,24 @@ import java.util.Map; import java.util.function.Supplier; import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkField; import software.amazon.awssdk.core.SdkPojo; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.protocols.core.OperationInfo; import software.amazon.awssdk.protocols.core.ProtocolMarshaller; -import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshallerBuilder; import static org.assertj.core.api.Assertions.assertThat; public class AWSQueryModeTest { - private static final SdkClientConfiguration EMPTY_CLIENT_CONFIGURATION = SdkClientConfiguration.builder() - .build(); private static final OperationInfo EMPTY_OPERATION_INFO = OperationInfo.builder() .httpMethod(SdkHttpMethod.POST) .hasImplicitPayloadMembers(true) .build(); - private final BaseAwsJsonProtocolFactory factory = AwsJsonProtocolFactory.builder() - .protocol(AwsJsonProtocol.AWS_JSON) - .clientConfiguration(EMPTY_CLIENT_CONFIGURATION) - .build(); - - private final Supplier structuredJsonFactory = getStructuredJsonFactory(factory); - - private final AwsJsonProtocolMetadata metadata = AwsJsonProtocolMetadata.builder() - .protocol(AwsJsonProtocol.AWS_JSON) - .contentType("application/json") - .build(); - - - static Supplier getStructuredJsonFactory(BaseAwsJsonProtocolFactory factory) { - return () -> { - try { - Method method = BaseAwsJsonProtocolFactory.class.getDeclaredMethod("getSdkFactory"); - method.setAccessible(true); - return (StructuredJsonFactory) method.invoke(factory); - } catch (Exception e) { - throw new RuntimeException(e); - } - }; - } - - /* * A simple test POJO to marshall */ @@ -97,52 +70,48 @@ public Map> sdkFieldNameToField() { @Test public void testMarshallWithAwsQueryCompatibleTrue() { - try { - ProtocolMarshaller marshaller = - JsonProtocolMarshallerBuilder.create() - .endpoint(new URI("http://localhost/")) - .jsonGenerator(structuredJsonFactory.get().createWriter("application/json")) - .contentType("application/json") - .operationInfo(EMPTY_OPERATION_INFO) - .sendExplicitNullForPayload(false) - .protocolMetadata(metadata) - .hasAwsQueryCompatible(true) - .build(); - SdkPojo testPojo = new TestPojo(); - - SdkHttpFullRequest result = marshaller.marshall(testPojo); - - assertThat(result.headers()).containsKey("x-amzn-query-mode"); - assertThat(result.headers().get("x-amzn-query-mode").get(0)).isEqualTo("true"); - - }catch (URISyntaxException e) { - throw new RuntimeException(e); - } - + SdkClientConfiguration clientConfig = + SdkClientConfiguration.builder() + .option(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, + ClientEndpointProvider.forEndpointOverride(URI.create("http://localhost"))) + .build(); + AwsJsonProtocolFactory factory = + AwsJsonProtocolFactory.builder() + .clientConfiguration(clientConfig) + .protocolVersion("1.1") + .protocol(AwsJsonProtocol.AWS_JSON) + .hasAwsQueryCompatible(true) + .build(); + + ProtocolMarshaller marshaller = factory.createProtocolMarshaller(EMPTY_OPERATION_INFO); + SdkPojo testPojo = new TestPojo(); + + SdkHttpFullRequest result = marshaller.marshall(testPojo); + + assertThat(result.headers()).containsKey("x-amzn-query-mode"); + assertThat(result.headers().get("x-amzn-query-mode").get(0)).isEqualTo("true"); } @Test public void testMarshallWithNoAwsQueryCompatible() { - try { - ProtocolMarshaller marshaller = - JsonProtocolMarshallerBuilder.create() - .endpoint(new URI("http://localhost/")) - .jsonGenerator(structuredJsonFactory.get().createWriter("application/json")) - .contentType("application/json") - .operationInfo(EMPTY_OPERATION_INFO) - .sendExplicitNullForPayload(false) - .protocolMetadata(metadata) - .build(); - SdkPojo testPojo = new TestPojo(); - - SdkHttpFullRequest result = marshaller.marshall(testPojo); - - assertThat(result.headers()).doesNotContainKey("x-amzn-query-mode"); - - }catch (URISyntaxException e) { - throw new RuntimeException(e); - } - + SdkClientConfiguration clientConfig = + SdkClientConfiguration.builder() + .option(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, + ClientEndpointProvider.forEndpointOverride(URI.create("http://localhost"))) + .build(); + AwsJsonProtocolFactory factory = + AwsJsonProtocolFactory.builder() + .clientConfiguration(clientConfig) + .protocolVersion("1.1") + .protocol(AwsJsonProtocol.AWS_JSON) + .build(); + + ProtocolMarshaller marshaller = factory.createProtocolMarshaller(EMPTY_OPERATION_INFO); + SdkPojo testPojo = new TestPojo(); + + SdkHttpFullRequest result = marshaller.marshall(testPojo); + + assertThat(result.headers()).doesNotContainKey("x-amzn-query-mode"); } } From db2ade0a843d32663ed2f7546ae8d1a6670bc312 Mon Sep 17 00:00:00 2001 From: yibole Date: Tue, 12 Nov 2024 12:54:12 -0800 Subject: [PATCH 4/4] lines adjusted --- .../amazon/awssdk/protocols/json/AWSQueryModeTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java index 0e77866839a2..ad35b8df5ecf 100644 --- a/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java +++ b/core/protocols/aws-json-protocol/src/test/java/software/amazon/awssdk/protocols/json/AWSQueryModeTest.java @@ -15,13 +15,10 @@ package software.amazon.awssdk.protocols.json; -import java.lang.reflect.Method; import java.net.URI; -import java.net.URISyntaxException; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkField;