diff --git a/docs/source/1.0/spec/http-protocol-compliance-tests.rst b/docs/source/1.0/spec/http-protocol-compliance-tests.rst index a5ef5c1241c..014f336d38b 100644 --- a/docs/source/1.0/spec/http-protocol-compliance-tests.rst +++ b/docs/source/1.0/spec/http-protocol-compliance-tests.rst @@ -103,6 +103,17 @@ that support the following members: - ``string`` - **Required**. The request-target of the HTTP request, not including the query string (for example, "/foo/bar"). + * - host + - ``string`` + - The host / endpoint provided to the client, not including the path or + scheme (for example, "example.com"). + * - resolvedHost + - ``string`` + - The host / endpoint that the client should send to, not including the + path or scheme (for example, "prefix.example.com"). + + This can differ from the host provided to the client if, for instance, + the operation has a member with the :ref:`endpoint-trait`. * - authScheme - shape ID - A shape ID that specifies the optional authentication scheme to diff --git a/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpRequestTestCase.java b/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpRequestTestCase.java index 1f7150a5bd9..f59f65488f8 100644 --- a/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpRequestTestCase.java +++ b/smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/HttpRequestTestCase.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import software.amazon.smithy.model.node.ArrayNode; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; @@ -32,12 +33,16 @@ public final class HttpRequestTestCase extends HttpMessageTestCase implements To private static final String METHOD = "method"; private static final String URI = "uri"; + private static final String HOST = "host"; + private static final String RESOLVED_HOST = "resolvedHost"; private static final String QUERY_PARAMS = "queryParams"; private static final String FORBID_QUERY_PARAMS = "forbidQueryParams"; private static final String REQUIRE_QUERY_PARAMS = "requireQueryParams"; private final String method; private final String uri; + private final String host; + private final String resolvedHost; private final List queryParams; private final List forbidQueryParams; private final List requireQueryParams; @@ -46,6 +51,8 @@ private HttpRequestTestCase(Builder builder) { super(builder); method = SmithyBuilder.requiredState(METHOD, builder.method); uri = SmithyBuilder.requiredState(URI, builder.uri); + host = builder.host; + resolvedHost = builder.resolvedHost; queryParams = ListUtils.copyOf(builder.queryParams); forbidQueryParams = ListUtils.copyOf(builder.forbidQueryParams); requireQueryParams = ListUtils.copyOf(builder.requireQueryParams); @@ -59,6 +66,14 @@ public String getUri() { return uri; } + public Optional getHost() { + return Optional.ofNullable(host); + } + + public Optional getResolvedHost() { + return Optional.ofNullable(resolvedHost); + } + public List getQueryParams() { return queryParams; } @@ -77,6 +92,8 @@ public static HttpRequestTestCase fromNode(Node node) { ObjectNode o = node.expectObjectNode(); builder.method(o.expectStringMember(METHOD).getValue()); builder.uri(o.expectStringMember(URI).getValue()); + o.getStringMember(HOST).ifPresent(stringNode -> builder.host(stringNode.getValue())); + o.getStringMember(RESOLVED_HOST).ifPresent(stringNode -> builder.resolvedHost(stringNode.getValue())); o.getArrayMember(QUERY_PARAMS).ifPresent(queryParams -> { builder.queryParams(queryParams.getElementsAs(StringNode::getValue)); }); @@ -94,6 +111,8 @@ public Node toNode() { ObjectNode.Builder node = super.toNode().expectObjectNode().toBuilder(); node.withMember(METHOD, getMethod()); node.withMember(URI, getUri()); + node.withOptionalMember(HOST, getHost().map(StringNode::from)); + node.withOptionalMember(RESOLVED_HOST, getResolvedHost().map(StringNode::from)); if (!queryParams.isEmpty()) { node.withMember(QUERY_PARAMS, ArrayNode.fromStrings(getQueryParams())); } @@ -114,6 +133,8 @@ public Builder toBuilder() { .queryParams(getQueryParams()) .forbidQueryParams(getForbidQueryParams()) .requireQueryParams(getRequireQueryParams()); + getHost().ifPresent(builder::host); + getResolvedHost().ifPresent(builder::resolvedHost); updateBuilder(builder); return builder; } @@ -129,6 +150,8 @@ public static final class Builder extends HttpMessageTestCase.Builder queryParams = new ArrayList<>(); private final List forbidQueryParams = new ArrayList<>(); private final List requireQueryParams = new ArrayList<>(); @@ -145,6 +168,16 @@ public Builder uri(String uri) { return this; } + public Builder host(String host) { + this.host = host; + return this; + } + + public Builder resolvedHost(String resolvedHost) { + this.resolvedHost = resolvedHost; + return this; + } + public Builder queryParams(List queryParams) { this.queryParams.clear(); this.queryParams.addAll(queryParams); diff --git a/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy b/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy index dc8a8a7e008..f8db846d3ed 100644 --- a/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy +++ b/smithy-protocol-test-traits/src/main/resources/META-INF/smithy/smithy.test.smithy @@ -37,6 +37,17 @@ structure HttpRequestTestCase { @length(min: 1) uri: String, + /// The host / endpoint provided to the client, not including the path + /// or scheme (for example, "example.com"). + host: String, + + /// The host / endpoint that the client should send to, not including + /// the path or scheme (for example, "prefix.example.com"). + /// + /// This can differ from the host provided to the client if the `hostPrefix` + /// member of the `endpoint` trait is set, for instance. + resolvedHost: String, + /// The optional authentication scheme shape ID to assume. It's /// possible that specific authentication schemes might influence /// the serialization logic of an HTTP request. diff --git a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy index f57e678a6cf..35a6800803d 100644 --- a/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy +++ b/smithy-protocol-test-traits/src/test/resources/software/amazon/smithy/protocoltests/traits/errorfiles/all-request-features.smithy @@ -19,6 +19,8 @@ structure testScheme {} authScheme: testScheme, method: "POST", uri: "/", + host: "example.com", + resolvedHost: "prefix.example.com", queryParams: ["foo=baz"], forbidQueryParams: ["Nope"], requireQueryParams: ["Yap"],