Skip to content

Commit 2a1d39e

Browse files
committed
Fix httpHeader and httpPrefixHeaders protocol tests
1 parent 857db19 commit 2a1d39e

File tree

6 files changed

+32
-15
lines changed

6 files changed

+32
-15
lines changed

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ public class RestJson1ProtocolTests {
3333
private static final String EMPTY_BODY = "";
3434

3535
@HttpClientRequestTests
36-
@ProtocolTestFilter(
37-
skipTests = {
38-
"RestJsonHttpEmptyPrefixHeadersRequestClient" //FIXME https://github.com/smithy-lang/smithy-java/issues/647
39-
})
4036
public void requestTest(DataStream expected, DataStream actual) {
4137
assertThat(expected.hasKnownLength())
4238
.isTrue()

aws/client/aws-client-restxml/src/it/java/software/amazon/smithy/java/aws/client/restxml/RestXmlProtocolTests.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public class RestXmlProtocolTests {
3838
skipTests = {
3939
"SDKAppliedContentEncoding_restXml",
4040
"SDKAppendedGzipAfterProvidedEncoding_restXml",
41-
"HttpEmptyPrefixHeadersRequestClient" //FIXME https://github.com/smithy-lang/smithy-java/issues/647
4241
})
4342
public void requestTest(DataStream expected, DataStream actual) {
4443
if (expected.contentLength() != 0) {

aws/server/aws-server-restjson/src/it/java/software/amazon/smithy/java/aws/server/restjson/AwsRestJson1ProtocolTests.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ public class AwsRestJson1ProtocolTests {
4545

4646
// Header splitting needs work.
4747
"RestJsonInputAndOutputWithQuotedStringHeaders",
48-
"RestJsonHttpEmptyPrefixHeadersRequestServer" //FIXME https://github.com/smithy-lang/smithy-java/issues/647
4948
},
5049
skipOperations = {
5150
"aws.protocoltests.restjson#DocumentType",
@@ -80,8 +79,6 @@ public void requestTest(Runnable test) {
8079
"RestJsonEmptyComplexErrorWithNoMessage",
8180
//TODO this breaks because of Validation and errorCorrection doesn't handle that.
8281
"RestJsonServerPopulatesNestedDefaultValuesWhenMissingInInResponseParams",
83-
"RestJsonHttpEmptyPrefixHeadersResponseServer" //FIXME https://github.com/smithy-lang/smithy-java/issues/647
84-
8582
})
8683
public void responseTest(DataStream expected, DataStream actual) {
8784
assertThat(expected.hasKnownLength())

http/http-binding/src/main/java/software/amazon/smithy/java/http/binding/HttpBindingSerializer.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
import java.io.ByteArrayOutputStream;
99
import java.util.ArrayList;
10+
import java.util.HashSet;
1011
import java.util.LinkedHashMap;
1112
import java.util.List;
1213
import java.util.Map;
14+
import java.util.Set;
1315
import java.util.StringJoiner;
1416
import java.util.TreeMap;
1517
import java.util.concurrent.Flow;
@@ -57,6 +59,7 @@ final class HttpBindingSerializer extends SpecificShapeSerializer implements Sha
5759
private final Map<String, String> labels = new LinkedHashMap<>();
5860
private final Map<String, List<String>> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
5961
private final QueryStringBuilder queryStringParams = new QueryStringBuilder();
62+
private final Set<String> namesFromHttpHeader = new HashSet<>();
6063

6164
private ShapeSerializer shapeBodySerializer;
6265
private ByteArrayOutputStream shapeBodyOutput;
@@ -98,6 +101,13 @@ public void writeStruct(Schema schema, SerializableStruct struct) {
98101
responseStatus = bindingMatcher.responseStatus();
99102
}
100103

104+
// Prescanning names from @httpHeader for @httpPrefixHeaders
105+
for (var member : schema.members()) {
106+
if (member.hasTrait(TraitKey.HTTP_HEADER_TRAIT)) {
107+
namesFromHttpHeader.add(member.expectTrait(TraitKey.HTTP_HEADER_TRAIT).getValue());
108+
}
109+
}
110+
101111
if (allowEmptyStructPayload || bindingMatcher.writeBody(omitEmptyPayload)) {
102112
shapeBodyOutput = new ByteArrayOutputStream();
103113
shapeBodySerializer = payloadCodec.createSerializer(shapeBodyOutput);
@@ -236,7 +246,8 @@ protected ShapeSerializer before(Schema schema) {
236246
case STATUS -> new ResponseStatusSerializer(i -> serializer.responseStatus = i);
237247
case PREFIX_HEADERS -> new HttpPrefixHeadersSerializer(
238248
schema.expectTrait(TraitKey.HTTP_PREFIX_HEADERS_TRAIT).getValue(),
239-
serializer.headerConsumer);
249+
serializer.headerConsumer,
250+
serializer.namesFromHttpHeader);
240251
case QUERY_PARAMS -> new HttpQueryParamsSerializer(serializer.queryStringParams::add);
241252
case BODY -> ShapeSerializer.nullSerializer(); // handled in HttpBindingSerializer#writeStruct.
242253
case PAYLOAD -> {

http/http-binding/src/main/java/software/amazon/smithy/java/http/binding/HttpPrefixHeadersDeserializer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ public <T> void readStringMap(Schema schema, T state, MapMemberConsumer<String,
3232
var prefix = trait.getValue().toLowerCase(Locale.ENGLISH);
3333
for (var entry : headers) {
3434
var name = entry.getKey();
35-
if (PrefixConstants.OMITTED_HEADER_NAMES.contains(name) || !name.startsWith(prefix)) {
35+
var lowerCaseName = name.toLowerCase(Locale.ENGLISH);
36+
if (PrefixConstants.OMITTED_HEADER_NAMES.contains(lowerCaseName)
37+
|| !lowerCaseName.startsWith(prefix)) {
3638
continue;
3739
}
3840
consumer.accept(state, name.substring(prefix.length()), new HeaderValueDeserializer(name));

http/http-binding/src/main/java/software/amazon/smithy/java/http/binding/HttpPrefixHeadersSerializer.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package software.amazon.smithy.java.http.binding;
77

8+
import java.util.Set;
89
import java.util.function.BiConsumer;
910
import software.amazon.smithy.java.core.schema.Schema;
1011
import software.amazon.smithy.java.core.serde.MapSerializer;
@@ -21,17 +22,23 @@ final class HttpPrefixHeadersSerializer extends SpecificShapeSerializer {
2122

2223
private final PrefixHeadersMapSerializer prefixHeadersMapSerializer;
2324

24-
HttpPrefixHeadersSerializer(String prefix, BiConsumer<String, String> headerConsumer) {
25-
prefixHeadersMapSerializer = new PrefixHeadersMapSerializer(prefix, headerConsumer);
25+
HttpPrefixHeadersSerializer(
26+
String prefix,
27+
BiConsumer<String, String> headerConsumer,
28+
Set<String> namesFromHttpHeader
29+
) {
30+
prefixHeadersMapSerializer = new PrefixHeadersMapSerializer(prefix, headerConsumer, namesFromHttpHeader);
2631
}
2732

2833
@Override
2934
public <T> void writeMap(Schema schema, T mapState, int size, BiConsumer<T, MapSerializer> consumer) {
3035
consumer.accept(mapState, prefixHeadersMapSerializer);
3136
}
3237

33-
private record PrefixHeadersMapSerializer(String prefix, BiConsumer<String, String> headerConsumer) implements
34-
MapSerializer {
38+
private record PrefixHeadersMapSerializer(
39+
String prefix,
40+
BiConsumer<String, String> headerConsumer,
41+
Set<String> namesFromHttpHeader) implements MapSerializer {
3542
@Override
3643
public <K> void writeEntry(
3744
Schema keySchema,
@@ -42,7 +49,12 @@ public <K> void writeEntry(
4249
valueSerializer.accept(keyState, new SpecificShapeSerializer() {
4350
@Override
4451
public void writeString(Schema schema, String value) {
45-
headerConsumer.accept(prefix + key, value);
52+
var headerName = prefix + key;
53+
// HttpHeader takes precedence if prefixHeader's value is empty.
54+
// Smithy's validator will complain if prefixHeader's value is not empty and duplicate found
55+
if (!namesFromHttpHeader.contains(headerName)) {
56+
headerConsumer.accept(headerName, value);
57+
}
4658
}
4759
});
4860
}

0 commit comments

Comments
 (0)