diff --git a/docs/source/1.0/spec/core/http-traits.rst b/docs/source/1.0/spec/core/http-traits.rst index ffc3c74d471..dc7b5a7834b 100644 --- a/docs/source/1.0/spec/core/http-traits.rst +++ b/docs/source/1.0/spec/core/http-traits.rst @@ -805,6 +805,23 @@ Serialization rules: Smithy models SHOULD carefully consider the maximum allowed length of each member that is bound to an HTTP query string or path. +.. _httpResponseCode-trait: + +``httpResponseCode`` trait +========================== + +Summary + Indicates that the structure member represents an HTTP response + status code. +Trait selector + ``structure > member :test(> integer)`` +Value type + Annotation trait. + +The value MAY differ from the HTTP status code provided on the response. +Explicitly modeling this as a field can be helpful for services that wish to +provide different response codes for an operation, like 200 or 201 for a PUT +operation. .. _cors-trait: diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpResponseCodeTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpResponseCodeTrait.java new file mode 100644 index 00000000000..e67815d9864 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpResponseCodeTrait.java @@ -0,0 +1,43 @@ +/* + * Copyright 2020 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.smithy.model.traits; + +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.shapes.ShapeId; + +/** + * Indicates that the structure member represents the HTTP response + * status code. This MAY differ from the HTTP status code provided + * in the response. + */ +public final class HttpResponseCodeTrait extends AnnotationTrait { + public static final ShapeId ID = ShapeId.from("smithy.api#httpResponseCode"); + + public HttpResponseCodeTrait(ObjectNode node) { + super(ID, node); + } + + public HttpResponseCodeTrait() { + this(Node.objectNode()); + } + + public static final class Provider extends AnnotationTrait.Provider { + public Provider() { + super(ID, HttpResponseCodeTrait::new); + } + } +} diff --git a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService index cba60b32f01..f7e3d95ea84 100644 --- a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService +++ b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.traits.TraitService @@ -18,6 +18,7 @@ software.amazon.smithy.model.traits.HttpLabelTrait$Provider software.amazon.smithy.model.traits.HttpPayloadTrait$Provider software.amazon.smithy.model.traits.HttpPrefixHeadersTrait$Provider software.amazon.smithy.model.traits.HttpQueryTrait$Provider +software.amazon.smithy.model.traits.HttpResponseCodeTrait$Provider software.amazon.smithy.model.traits.HttpTrait$Provider software.amazon.smithy.model.traits.IdempotencyTokenTrait$Provider software.amazon.smithy.model.traits.IdempotentTrait$Provider diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy index 73640c151fb..f8157931912 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy @@ -574,6 +574,14 @@ structure httpPayload {} @tags(["diff.error.const"]) integer httpError +/// Indicates that the structure member represents the HTTP response +/// status code. The value MAY differ from the HTTP status code provided +/// on the response. +@trait(selector: "structure > member :test(> integer)", + structurallyExclusive: "member") +@tags(["diff.error.const"]) +structure httpResponseCode {} + /// Defines how a service supports cross-origin resource sharing. @trait(selector: "service") @tags(["diff.error.remove"]) diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpResponseCodeTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpResponseCodeTraitTest.java new file mode 100644 index 00000000000..436ed69c514 --- /dev/null +++ b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpResponseCodeTraitTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2020 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.smithy.model.traits; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Optional; +import org.junit.jupiter.api.Test; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.shapes.ShapeId; + +public class HttpResponseCodeTraitTest { + @Test + public void loadsTrait() { + TraitFactory provider = TraitFactory.createServiceFactory(); + Optional trait = provider.createTrait( + ShapeId.from("smithy.api#httpResponseCode"), ShapeId.from("ns.qux#Foo$bar"), Node.objectNode()); + + assertTrue(trait.isPresent()); + assertThat(trait.get(), instanceOf(HttpResponseCodeTrait.class)); + assertThat(trait.get().toNode(), equalTo(Node.objectNode())); + } +}