Skip to content

Commit cb64f4f

Browse files
committed
Add document discrinator sanitizer for JSON protocols
1 parent 2c88988 commit cb64f4f

File tree

12 files changed

+137
-7
lines changed

12 files changed

+137
-7
lines changed

aws/client/aws-client-awsjson/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ dependencies {
2020

2121
val generator = "software.amazon.smithy.java.protocoltests.generators.ProtocolTestGenerator"
2222
addGenerateSrcsTask(generator, "awsJson1_0", "aws.protocoltests.json10#JsonRpc10")
23+
addGenerateSrcsTask(generator, "awsJson1_1", "aws.protocoltests.json#JsonProtocol")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.java.client.aws.jsonprotocols;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
10+
import java.nio.charset.StandardCharsets;
11+
import software.amazon.smithy.java.io.ByteBufferUtils;
12+
import software.amazon.smithy.java.io.datastream.DataStream;
13+
import software.amazon.smithy.java.protocoltests.harness.*;
14+
import software.amazon.smithy.model.node.Node;
15+
import software.amazon.smithy.model.node.ObjectNode;
16+
17+
@ProtocolTest(
18+
service = "aws.protocoltests.json#JsonProtocol",
19+
testType = TestType.CLIENT)
20+
public class AwsJson11ProtocolTests {
21+
@HttpClientRequestTests
22+
@ProtocolTestFilter(
23+
skipTests = {
24+
"SDKAppliedContentEncoding_awsJson1_1",
25+
"SDKAppendsGzipAndIgnoresHttpProvidedEncoding_awsJson1_1",
26+
})
27+
public void requestTest(DataStream expected, DataStream actual) {
28+
Node expectedNode = ObjectNode.objectNode();
29+
if (expected.contentLength() != 0) {
30+
expectedNode = Node.parse(new String(ByteBufferUtils.getBytes(expected.asByteBuffer()),
31+
StandardCharsets.UTF_8));
32+
}
33+
Node actualNode = Node.parse(new StringBuildingSubscriber(actual).getResult());
34+
assertEquals(expectedNode, actualNode);
35+
}
36+
37+
@HttpClientResponseTests
38+
@ProtocolTestFilter(
39+
skipTests = {
40+
"AwsJson11FooErrorUsingCode",
41+
"AwsJson11FooErrorUsingCodeAndNamespace",
42+
"AwsJson11FooErrorUsingCodeUriAndNamespace",
43+
})
44+
public void responseTest(Runnable test) {
45+
test.run();
46+
}
47+
}

aws/client/aws-client-awsjson/src/it/java/software/amazon/smithy/java/client/aws/jsonprotocols/AwsJson1ProtocolTests.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ public void requestTest(DataStream expected, DataStream actual) {
5555
"AwsJson10FooErrorUsingCode",
5656
"AwsJson10FooErrorUsingCodeAndNamespace",
5757
"AwsJson10FooErrorUsingCodeUriAndNamespace",
58-
"AwsJson10FooErrorWithDunderTypeUriAndNamespace"
59-
6058
},
6159
skipOperations = "aws.protocoltests.json10#OperationWithRequiredMembersWithDefaults")
6260
public void responseTest(Runnable test) {

aws/client/aws-client-awsjson/src/main/java/software/amazon/smithy/java/aws/client/awsjson/AwsJson11Protocol.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import software.amazon.smithy.java.client.core.ClientProtocol;
1111
import software.amazon.smithy.java.client.core.ClientProtocolFactory;
1212
import software.amazon.smithy.java.client.core.ProtocolSettings;
13+
import software.amazon.smithy.java.json.ErrorTypeSanitizer;
1314
import software.amazon.smithy.model.shapes.ShapeId;
1415

1516
/**
@@ -24,7 +25,7 @@ public final class AwsJson11Protocol extends AwsJsonProtocol {
2425
* discriminator of documents that use relative shape IDs.
2526
*/
2627
public AwsJson11Protocol(ShapeId service) {
27-
super(TRAIT_ID, service);
28+
super(TRAIT_ID, service, ErrorTypeSanitizer::REMOVE_NAMESPACE_AND_URI);
2829
}
2930

3031
@Override

aws/client/aws-client-awsjson/src/main/java/software/amazon/smithy/java/aws/client/awsjson/AwsJson1Protocol.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import software.amazon.smithy.java.client.core.ClientProtocol;
1111
import software.amazon.smithy.java.client.core.ClientProtocolFactory;
1212
import software.amazon.smithy.java.client.core.ProtocolSettings;
13+
import software.amazon.smithy.java.json.ErrorTypeSanitizer;
1314
import software.amazon.smithy.model.shapes.ShapeId;
1415

1516
/**
@@ -24,7 +25,7 @@ public final class AwsJson1Protocol extends AwsJsonProtocol {
2425
* discriminator of documents that use relative shape IDs.
2526
*/
2627
public AwsJson1Protocol(ShapeId service) {
27-
super(TRAIT_ID, service);
28+
super(TRAIT_ID, service, ErrorTypeSanitizer::REMOVE_URI);
2829
}
2930

3031
@Override

aws/client/aws-client-awsjson/src/main/java/software/amazon/smithy/java/aws/client/awsjson/AwsJsonProtocol.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.nio.charset.StandardCharsets;
1010
import java.util.List;
1111
import java.util.Map;
12+
import java.util.function.Function;
1213
import software.amazon.smithy.java.client.http.AmznErrorHeaderExtractor;
1314
import software.amazon.smithy.java.client.http.HttpClientProtocol;
1415
import software.amazon.smithy.java.client.http.HttpErrorDeserializer;
@@ -39,10 +40,14 @@ abstract sealed class AwsJsonProtocol extends HttpClientProtocol permits AwsJson
3940
* @param service The service ID used to make X-Amz-Target, and the namespace is used when finding the
4041
* discriminator of documents that use relative shape IDs.
4142
*/
42-
public AwsJsonProtocol(ShapeId trait, ShapeId service) {
43+
public AwsJsonProtocol(ShapeId trait, ShapeId service, Function<String, String> errorTypeSanitizer) {
4344
super(trait);
4445
this.service = service;
45-
this.codec = JsonCodec.builder().defaultNamespace(service.getNamespace()).build();
46+
this.codec = JsonCodec.builder()
47+
.defaultNamespace(service.getNamespace())
48+
.errorTypeSanitizer(errorTypeSanitizer)
49+
.useTimestampFormat(true)
50+
.build();
4651

4752
this.errorDeserializer = HttpErrorDeserializer.builder()
4853
.codec(codec)

aws/client/aws-client-restjson/src/it/java/software/amazon/smithy/java/client/aws/restjson/RestJson1ProtocolTests.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ public void requestTest(DataStream expected, DataStream actual) {
6161
"RestJsonFooErrorUsingCode",
6262
"RestJsonFooErrorUsingCodeAndNamespace",
6363
"RestJsonFooErrorUsingCodeUriAndNamespace",
64-
"RestJsonFooErrorWithDunderTypeUriAndNamespace"
6564
})
6665
public void responseTest(Runnable test) {
6766
test.run();

aws/client/aws-client-restjson/src/main/java/software/amazon/smithy/java/aws/client/restjson/RestJsonClientProtocol.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import software.amazon.smithy.java.core.serde.event.EventStreamingException;
3030
import software.amazon.smithy.java.http.api.HttpRequest;
3131
import software.amazon.smithy.java.http.binding.RequestSerializer;
32+
import software.amazon.smithy.java.json.ErrorTypeSanitizer;
3233
import software.amazon.smithy.java.json.JsonCodec;
3334
import software.amazon.smithy.model.shapes.ShapeId;
3435
import software.amazon.smithy.model.shapes.ShapeType;
@@ -52,6 +53,7 @@ public RestJsonClientProtocol(ShapeId service) {
5253
.useJsonName(true)
5354
.useTimestampFormat(true)
5455
.defaultNamespace(service.getNamespace())
56+
.errorTypeSanitizer(ErrorTypeSanitizer::REMOVE_NAMESPACE_AND_URI)
5557
.build();
5658

5759
this.errorDeserializer = HttpErrorDeserializer.builder()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.java.json;
7+
8+
/**
9+
* A util class contains the sanitizer functions to process {@code __type} field from the document
10+
*
11+
* <p>For example, given {@code __type = "aws.protocoltests.restjson#FooError:http://abc.com"},
12+
* different protocols have different requirements for the {@code __type} field. This class provides
13+
* sanitizers to remove trailing URIs or leading namespaces from {@code __type}.
14+
*/
15+
public class ErrorTypeSanitizer {
16+
public static String REMOVE_URI(String text) {
17+
if (text == null) {
18+
return null;
19+
}
20+
var colon = text.indexOf(':');
21+
if (colon > 0) {
22+
text = text.substring(0, colon);
23+
}
24+
return text;
25+
}
26+
27+
public static String REMOVE_NAMESPACE_AND_URI(String text) {
28+
if (text == null) {
29+
return null;
30+
}
31+
var hash = text.indexOf('#');
32+
if (hash > 0) {
33+
text = text.substring(hash + 1);
34+
}
35+
return REMOVE_URI(text);
36+
}
37+
}

codecs/json-codec/src/main/java/software/amazon/smithy/java/json/JsonCodec.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import java.io.OutputStream;
99
import java.nio.ByteBuffer;
10+
import java.util.function.Function;
1011
import software.amazon.smithy.java.core.serde.Codec;
1112
import software.amazon.smithy.java.core.serde.ShapeDeserializer;
1213
import software.amazon.smithy.java.core.serde.ShapeSerializer;
@@ -174,5 +175,16 @@ Builder overrideSerdeProvider(JsonSerdeProvider provider) {
174175
settingsBuilder.overrideSerdeProvider(provider);
175176
return this;
176177
}
178+
179+
/**
180+
* Uses a custom error type sanitizer to process the {@code __type} field.
181+
*
182+
* @param errorTypeSanitizer the type sanitizer to use.
183+
* @return the builder.
184+
*/
185+
public Builder errorTypeSanitizer(Function<String, String> errorTypeSanitizer) {
186+
settingsBuilder.errorTypeSanitizer(errorTypeSanitizer);
187+
return this;
188+
}
177189
}
178190
}

0 commit comments

Comments
 (0)