diff --git a/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst b/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst index 62add0a103b..0c8bde8099d 100644 --- a/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst +++ b/docs/source/1.0/spec/aws/aws-ec2-query-protocol.rst @@ -180,6 +180,11 @@ that affect serialization: - Description * - :ref:`cors ` - Indicates that the service supports CORS. + * - :ref:`endpoint ` + - Configures a custom operation endpoint. + * - :ref:`hostLabel ` + - Binds a top-level operation input structure member to a label in + the hostPrefix of an endpoint trait. * - :ref:`ec2QueryName ` - By default, the form-urlencoded key segments used in serialized structures are the same as a structure member name. The ``ec2QueryName`` diff --git a/docs/source/1.0/spec/aws/aws-json.rst.template b/docs/source/1.0/spec/aws/aws-json.rst.template index 0d2bf5d48f5..1fb6575c01f 100644 --- a/docs/source/1.0/spec/aws/aws-json.rst.template +++ b/docs/source/1.0/spec/aws/aws-json.rst.template @@ -13,6 +13,11 @@ that affect serialization: - Description * - :ref:`cors ` - Indicates that the service supports CORS. + * - :ref:`endpoint ` + - Configures a custom operation endpoint. + * - :ref:`hostLabel ` + - Binds a top-level operation input structure member to a label in + the hostPrefix of an endpoint trait. * - :ref:`jsonName ` - By default, the JSON property names used in serialized structures are the same as a structure member name. The ``jsonName`` trait changes diff --git a/docs/source/1.0/spec/aws/aws-query-protocol.rst b/docs/source/1.0/spec/aws/aws-query-protocol.rst index b115dfa6e7f..a9387b0f3ec 100644 --- a/docs/source/1.0/spec/aws/aws-query-protocol.rst +++ b/docs/source/1.0/spec/aws/aws-query-protocol.rst @@ -73,6 +73,11 @@ that affect serialization: - Description * - :ref:`cors ` - Indicates that the service supports CORS. + * - :ref:`endpoint ` + - Configures a custom operation endpoint. + * - :ref:`hostLabel ` + - Binds a top-level operation input structure member to a label in + the hostPrefix of an endpoint trait. * - :ref:`xmlAttrubute ` - Serializes an object property as an XML attribute rather than a nested XML element. diff --git a/smithy-aws-protocol-tests/model/awsJson1_0/endpoints.smithy b/smithy-aws-protocol-tests/model/awsJson1_0/endpoints.smithy new file mode 100644 index 00000000000..2cb6d938204 --- /dev/null +++ b/smithy-aws-protocol-tests/model/awsJson1_0/endpoints.smithy @@ -0,0 +1,57 @@ +// This file defines tests to ensure that implementations support the endpoint +// trait and other features that modify the host. + +$version: "1.0" + +namespace aws.protocoltests.json10 + +use aws.protocols#awsJson1_0 +use smithy.test#httpRequestTests + +@httpRequestTests([ + { + id: "AwsJson10EndpointTrait", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait.""", + protocol: awsJson1_0, + method: "POST", + uri: "/", + body: "{}", + host: "example.com", + resolvedHost: "foo.example.com", + } +]) +@endpoint(hostPrefix: "foo.") +operation EndpointOperation {} + + +@httpRequestTests([ + { + id: "AwsJson10EndpointTraitWithHostLabel", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait, and can use the host label trait to define + further customization based on user input.""", + protocol: awsJson1_0, + method: "POST", + uri: "/", + body: "{\"label\": \"bar\"}", + bodyMediaType: "application/json", + host: "example.com", + resolvedHost: "foo.bar.example.com", + params: { + label: "bar", + }, + } +]) +@endpoint(hostPrefix: "foo.{label}.") +operation EndpointWithHostLabelOperation { + input: HostLabelInput, +} + +structure HostLabelInput { + @required + @hostLabel + label: String, +} diff --git a/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy b/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy index bfb2d404cfa..0edffc5dd40 100644 --- a/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy +++ b/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy @@ -20,5 +20,9 @@ service JsonRpc10 { // Errors GreetingWithErrors, JsonUnions, + + // @endpoint and @hostLabel trait tests + EndpointOperation, + EndpointWithHostLabelOperation, ] } diff --git a/smithy-aws-protocol-tests/model/awsJson1_1/endpoints.smithy b/smithy-aws-protocol-tests/model/awsJson1_1/endpoints.smithy new file mode 100644 index 00000000000..4181b86c216 --- /dev/null +++ b/smithy-aws-protocol-tests/model/awsJson1_1/endpoints.smithy @@ -0,0 +1,57 @@ +// This file defines tests to ensure that implementations support the endpoint +// trait and other features that modify the host. + +$version: "1.0" + +namespace aws.protocoltests.json + +use aws.protocols#awsJson1_1 +use smithy.test#httpRequestTests + +@httpRequestTests([ + { + id: "AwsJson11EndpointTrait", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait.""", + protocol: awsJson1_1, + method: "POST", + uri: "/", + body: "{}", + host: "example.com", + resolvedHost: "foo.example.com", + } +]) +@endpoint(hostPrefix: "foo.") +operation EndpointOperation {} + + +@httpRequestTests([ + { + id: "AwsJson11EndpointTraitWithHostLabel", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait, and can use the host label trait to define + further customization based on user input.""", + protocol: awsJson1_1, + method: "POST", + uri: "/", + body: "{\"label\": \"bar\"}", + bodyMediaType: "application/json", + host: "example.com", + resolvedHost: "foo.bar.example.com", + params: { + label: "bar", + }, + } +]) +@endpoint(hostPrefix: "foo.{label}.") +operation EndpointWithHostLabelOperation { + input: HostLabelInput, +} + +structure HostLabelInput { + @required + @hostLabel + label: String, +} diff --git a/smithy-aws-protocol-tests/model/awsJson1_1/main.smithy b/smithy-aws-protocol-tests/model/awsJson1_1/main.smithy index 2aca91ab07f..9273027b70d 100644 --- a/smithy-aws-protocol-tests/model/awsJson1_1/main.smithy +++ b/smithy-aws-protocol-tests/model/awsJson1_1/main.smithy @@ -28,6 +28,10 @@ service JsonProtocol { NullOperation, GreetingWithErrors, JsonUnions, + + // @endpoint and @hostLabel trait tests + EndpointOperation, + EndpointWithHostLabelOperation, ], } diff --git a/smithy-aws-protocol-tests/model/awsQuery/endpoints.smithy b/smithy-aws-protocol-tests/model/awsQuery/endpoints.smithy new file mode 100644 index 00000000000..2f879a37cf5 --- /dev/null +++ b/smithy-aws-protocol-tests/model/awsQuery/endpoints.smithy @@ -0,0 +1,69 @@ +// This file defines tests to ensure that implementations support the endpoint +// trait and other features that modify the host. + +$version: "1.0" + +namespace aws.protocoltests.query + +use aws.protocols#awsQuery +use smithy.test#httpRequestTests + +@httpRequestTests([ + { + id: "AwsQueryEndpointTrait", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait.""", + protocol: awsQuery, + method: "POST", + uri: "/", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: """ + Action=EndpointOperation + &Version=2020-01-08""", + bodyMediaType: "application/x-www-form-urlencoded", + host: "example.com", + resolvedHost: "foo.example.com", + } +]) +@endpoint(hostPrefix: "foo.") +operation EndpointOperation {} + + +@httpRequestTests([ + { + id: "AwsQueryEndpointTraitWithHostLabel", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait, and can use the host label trait to define + further customization based on user input.""", + protocol: awsQuery, + method: "POST", + uri: "/", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: """ + Action=EndpointWithHostLabelOperation + &Version=2020-01-08 + &label=bar""", + bodyMediaType: "application/x-www-form-urlencoded", + host: "example.com", + resolvedHost: "foo.bar.example.com", + params: { + label: "bar", + }, + } +]) +@endpoint(hostPrefix: "foo.{label}.") +operation EndpointWithHostLabelOperation { + input: HostLabelInput, +} + +structure HostLabelInput { + @required + @hostLabel + label: String, +} diff --git a/smithy-aws-protocol-tests/model/awsQuery/main.smithy b/smithy-aws-protocol-tests/model/awsQuery/main.smithy index 0a430261fbe..b868503d4ca 100644 --- a/smithy-aws-protocol-tests/model/awsQuery/main.smithy +++ b/smithy-aws-protocol-tests/model/awsQuery/main.smithy @@ -54,5 +54,9 @@ service AwsQuery { // Output error tests GreetingWithErrors, + + // @endpoint and @hostLabel trait tests + EndpointOperation, + EndpointWithHostLabelOperation, ] } diff --git a/smithy-aws-protocol-tests/model/ec2Query/endpoints.smithy b/smithy-aws-protocol-tests/model/ec2Query/endpoints.smithy new file mode 100644 index 00000000000..657ce37dbba --- /dev/null +++ b/smithy-aws-protocol-tests/model/ec2Query/endpoints.smithy @@ -0,0 +1,69 @@ +// This file defines tests to ensure that implementations support the endpoint +// trait and other features that modify the host. + +$version: "1.0" + +namespace aws.protocoltests.ec2 + +use aws.protocols#ec2Query +use smithy.test#httpRequestTests + +@httpRequestTests([ + { + id: "Ec2QueryEndpointTrait", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait.""", + protocol: ec2Query, + method: "POST", + uri: "/", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: """ + Action=EndpointOperation + &Version=2020-01-08""", + bodyMediaType: "application/x-www-form-urlencoded", + host: "example.com", + resolvedHost: "foo.example.com", + } +]) +@endpoint(hostPrefix: "foo.") +operation EndpointOperation {} + + +@httpRequestTests([ + { + id: "Ec2QueryEndpointTraitWithHostLabel", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait, and can use the host label trait to define + further customization based on user input.""", + protocol: ec2Query, + method: "POST", + uri: "/", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: """ + Action=EndpointWithHostLabelOperation + &Version=2020-01-08 + &label=bar""", + bodyMediaType: "application/x-www-form-urlencoded", + host: "example.com", + resolvedHost: "foo.bar.example.com", + params: { + label: "bar", + }, + } +]) +@endpoint(hostPrefix: "foo.{label}.") +operation EndpointWithHostLabelOperation { + input: HostLabelInput, +} + +structure HostLabelInput { + @required + @hostLabel + label: String, +} diff --git a/smithy-aws-protocol-tests/model/ec2Query/main.smithy b/smithy-aws-protocol-tests/model/ec2Query/main.smithy index 955026e9c85..950572557a0 100644 --- a/smithy-aws-protocol-tests/model/ec2Query/main.smithy +++ b/smithy-aws-protocol-tests/model/ec2Query/main.smithy @@ -70,5 +70,9 @@ service AwsEc2 { // Output error tests GreetingWithErrors, + + // @endpoint and @hostLabel trait tests + EndpointOperation, + EndpointWithHostLabelOperation, ] } diff --git a/smithy-aws-protocol-tests/model/restJson1/endpoints.smithy b/smithy-aws-protocol-tests/model/restJson1/endpoints.smithy new file mode 100644 index 00000000000..f7bd74a566a --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/endpoints.smithy @@ -0,0 +1,59 @@ +// This file defines tests to ensure that implementations support the endpoint +// trait and other features that modify the host. + +$version: "1.0" + +namespace aws.protocoltests.restjson + +use aws.protocols#restJson1 +use smithy.test#httpRequestTests + +@httpRequestTests([ + { + id: "RestJsonEndpointTrait", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait.""", + protocol: restJson1, + method: "POST", + uri: "/EndpointOperation", + body: "", + host: "example.com", + resolvedHost: "foo.example.com", + } +]) +@endpoint(hostPrefix: "foo.") +@http(uri: "/EndpointOperation", method: "POST") +operation EndpointOperation {} + + +@httpRequestTests([ + { + id: "RestJsonEndpointTraitWithHostLabel", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait, and can use the host label trait to define + further customization based on user input.""", + protocol: restJson1, + method: "POST", + uri: "/EndpointOperation", + body: "{\"label\": \"bar\"}", + bodyMediaType: "application/json", + host: "example.com", + resolvedHost: "foo.bar.example.com", + params: { + label: "bar", + }, + } +]) +@endpoint(hostPrefix: "foo.{label}.") +@http(uri: "/EndpointWithHostLabelOperation", method: "POST") +operation EndpointWithHostLabelOperation { + input: HostLabelInput, +} + +structure HostLabelInput { + @required + @hostLabel + label: String, +} diff --git a/smithy-aws-protocol-tests/model/restJson1/main.smithy b/smithy-aws-protocol-tests/model/restJson1/main.smithy index ae2d50fe1bc..8e2a923124d 100644 --- a/smithy-aws-protocol-tests/model/restJson1/main.smithy +++ b/smithy-aws-protocol-tests/model/restJson1/main.smithy @@ -73,5 +73,9 @@ service RestJson { // Unions JsonUnions, + + // @endpoint and @hostLabel trait tests + EndpointOperation, + EndpointWithHostLabelOperation, ] } diff --git a/smithy-aws-protocol-tests/model/restXml/endpoints.smithy b/smithy-aws-protocol-tests/model/restXml/endpoints.smithy new file mode 100644 index 00000000000..b926237423d --- /dev/null +++ b/smithy-aws-protocol-tests/model/restXml/endpoints.smithy @@ -0,0 +1,100 @@ +// This file defines tests to ensure that implementations support the endpoint +// trait and other features that modify the host. + +$version: "1.0" + +namespace aws.protocoltests.restxml + +use aws.protocols#restXml +use smithy.test#httpRequestTests + +@httpRequestTests([ + { + id: "RestXmlEndpointTrait", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait.""", + protocol: restXml, + method: "POST", + uri: "/EndpointOperation", + body: "", + host: "example.com", + resolvedHost: "foo.example.com", + } +]) +@endpoint(hostPrefix: "foo.") +@http(uri: "/EndpointOperation", method: "POST") +operation EndpointOperation {} + + +@httpRequestTests([ + { + id: "RestXmlEndpointTraitWithHostLabel", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait, and can use the host label trait to define + further customization based on user input.""", + protocol: restXml, + method: "POST", + uri: "/EndpointOperation", + body: """ + + + + """, + bodyMediaType: "application/xml", + host: "example.com", + resolvedHost: "foo.bar.example.com", + params: { + label: "bar", + }, + } +]) +@endpoint(hostPrefix: "foo.{label}.") +@http(uri: "/EndpointWithHostLabelOperation", method: "POST") +operation EndpointWithHostLabelOperation { + input: HostLabelInput, +} + +structure HostLabelInput { + @required + @hostLabel + label: String, +} + +@httpRequestTests([ + { + id: "RestXmlEndpointTraitWithHostLabelAndHttpBinding", + documentation: """ + Operations can prepend to the given host if they define the + endpoint trait, and can use the host label trait to define + further customization based on user input. The label must also + be serialized in into any other location it is bound to, such + as the body or in this case an http header.""", + protocol: restXml, + method: "POST", + uri: "/EndpointOperation", + body: "", + bodyMediaType: "application/xml", + host: "example.com", + resolvedHost: "bar.example.com", + headers: { + "X-Amz-Account-Id": "bar", + }, + params: { + accountId: "bar", + }, + } +]) +@endpoint(hostPrefix: "{accountId}.") +@http(uri: "/EndpointWithHostLabelHeaderOperation", method: "POST") +operation EndpointWithHostLabelHeaderOperation { + input: HostLabelHeaderInput, +} + +structure HostLabelHeaderInput { + @required + @hostLabel + @httpHeader("X-Amz-Account-Id") + accountId: String, +} diff --git a/smithy-aws-protocol-tests/model/restXml/main.smithy b/smithy-aws-protocol-tests/model/restXml/main.smithy index 11a03075349..649040abd59 100644 --- a/smithy-aws-protocol-tests/model/restXml/main.smithy +++ b/smithy-aws-protocol-tests/model/restXml/main.smithy @@ -80,5 +80,10 @@ service RestXml { // @xmlNamespace trait tests XmlNamespaces, + + // @endpoint and @hostLabel trait tests + EndpointOperation, + EndpointWithHostLabelOperation, + EndpointWithHostLabelHeaderOperation, ] } diff --git a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.protocols.json b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.protocols.json index 7fe901fa2ff..18db45c7205 100644 --- a/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.protocols.json +++ b/smithy-aws-traits/src/main/resources/META-INF/smithy/aws.protocols.json @@ -98,7 +98,9 @@ "traits": [ "smithy.api#jsonName", "smithy.api#timestampFormat", - "smithy.api#cors" + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel" ] }, "smithy.api#documentation": "An RPC-based protocol that sends JSON payloads. This protocol does not use HTTP binding traits." @@ -122,7 +124,9 @@ "traits": [ "smithy.api#jsonName", "smithy.api#timestampFormat", - "smithy.api#cors" + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel" ] }, "smithy.api#documentation": "An RPC-based protocol that sends JSON payloads. This protocol does not use HTTP binding traits." @@ -142,7 +146,9 @@ "smithy.api#xmlName", "smithy.api#xmlNamespace", "smithy.api#timestampFormat", - "smithy.api#cors" + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel" ] }, "smithy.api#documentation": "An RPC-based protocol that sends 'POST' requests in the body as `x-www-form-urlencoded` strings and responses in XML documents. This protocol does not use HTTP binding traits.", @@ -164,7 +170,9 @@ "smithy.api#xmlName", "smithy.api#xmlNamespace", "smithy.api#timestampFormat", - "smithy.api#cors" + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel" ] }, "smithy.api#documentation": "An RPC-based protocol that sends 'POST' requests in the body as Amazon EC2 formatted `x-www-form-urlencoded` strings and responses in XML documents. This protocol does not use HTTP binding traits.",