diff --git a/smithy-aws-protocol-tests/build.gradle b/smithy-aws-protocol-tests/build.gradle index 6ebde5e69aa..8bef8f2f48c 100644 --- a/smithy-aws-protocol-tests/build.gradle +++ b/smithy-aws-protocol-tests/build.gradle @@ -28,4 +28,5 @@ dependencies { implementation project(":smithy-cli") implementation project(":smithy-protocol-test-traits") implementation project(":smithy-aws-traits") + api project(":smithy-validation-model") } diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/main.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/main.smithy new file mode 100644 index 00000000000..e75cf9c5a70 --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/main.smithy @@ -0,0 +1,25 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.api#service +use aws.protocols#restJson1 + +/// A REST JSON service that sends JSON requests and responses with validation applied +@service(sdkId: "Rest Json Validation Protocol") +@restJson1 +service RestJsonValidation { + version: "2021-08-19", + operations: [ + MalformedEnum, + MalformedLength, + MalformedLengthOverride, + MalformedPattern, + MalformedPatternOverride, + MalformedRange, + MalformedRangeOverride, + MalformedRequired, + RecursiveStructures, + SensitiveValidation + ] +} diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/malformed-enum.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-enum.smithy new file mode 100644 index 00000000000..58609772b97 --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-enum.smithy @@ -0,0 +1,208 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.protocols#restJson1 +use smithy.test#httpMalformedRequestTests +use smithy.framework#ValidationException + +@http(uri: "/MalformedEnum", method: "POST") +operation MalformedEnum { + input: MalformedEnumInput, + errors: [ValidationException] +} + +apply MalformedEnum @httpMalformedRequestTests([ + { + id: "RestJsonMalformedEnumString", + documentation: """ + When a string member does not contain a valid enum value, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedEnum", + body: """ + { "string" : $value:S }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/string' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", + "fieldList" : [{"message": "Value $value:L at '/string' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", "path": "/string"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "XYZ"] + } + }, + { + id: "RestJsonMalformedEnumList", + documentation: """ + When a list member value does not contain a valid enum value, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedEnum", + body: """ + { "list" : [$value:S] }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/list/0' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", + "fieldList" : [{"message": "Value $value:L at '/list/0' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", "path": "/list/0"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "XYZ"] + } + }, + { + id: "RestJsonMalformedEnumMapKey", + documentation: """ + When a map member's key does not contain a valid enum value, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedEnum", + body: """ + { "map" : { $value:S : "abc" } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/map' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", + "fieldList" : [{"message": "Value $value:L at '/map' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", "path": "/map"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "XYZ"] + } + }, + { + id: "RestJsonMalformedEnumMapValue", + documentation: """ + When a map member's value does not contain a valid enum value, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedEnum", + body: """ + { "map" : { "abc": $value:S } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/map/abc' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", + "fieldList" : [{"message": "Value $value:L at '/map/abc' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", "path": "/map/abc"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "XYZ"] + } + }, + { + id: "RestJsonMalformedEnumUnion", + documentation: """ + When a union member's value does not contain a valid enum value, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedEnum", + body: """ + { "union" : { "first": $value:S } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/union/first' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", + "fieldList" : [{"message": "Value $value:L at '/union/first' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", "path": "/union/first"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "XYZ"] + } + }, +]) + +structure MalformedEnumInput { + string: EnumString, + + list: EnumList, + + map: EnumMap, + + union: EnumUnion +} + +@enum([{value: "abc", name: "ABC"}, {value: "def", name: "DEF"}]) +string EnumString + +list EnumList { + member: EnumString +} + +map EnumMap { + key: EnumString, + value: EnumString +} + +union EnumUnion { + first: EnumString, + second: EnumString +} diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/malformed-length.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-length.smithy new file mode 100644 index 00000000000..223f7d0832f --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-length.smithy @@ -0,0 +1,595 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.protocols#restJson1 +use smithy.test#httpMalformedRequestTests +use smithy.framework#ValidationException + +@http(uri: "/MalformedLength", method: "POST") +operation MalformedLength { + input: MalformedLengthInput, + errors: [ValidationException] +} + +@http(uri: "/MalformedLengthOverride", method: "POST") +operation MalformedLengthOverride { + input: MalformedLengthOverrideInput, + errors: [ValidationException] +} + +apply MalformedLength @httpMalformedRequestTests([ + { + id: "RestJsonMalformedLengthBlob", + documentation: """ + When a blob member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "blob" : $value:S }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/blob' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/blob' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", "path": "/blob"}]}""" + } + } + }, + testParameters: { + value: ["YQ==", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="], + inputLength: ["1", "26"] + } + }, + { + id: "RestJsonMalformedLengthString", + documentation: """ + When a string member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "string" : $value:S }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/string' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/string' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", "path": "/string"}]}""" + } + } + }, + testParameters: { + value: ["a", "abcdefghijklmnopqrstuvwxyz"], + inputLength: ["1", "26"] + } + }, + { + id: "RestJsonMalformedLengthMinString", + documentation: """ + When a string member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "minString" : "a" }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length 1 at '/minString' failed to satisfy constraint: Member must have length greater than or equal to 2", + "fieldList" : [{"message": "Value with length 1 at '/minString' failed to satisfy constraint: Member must have length greater than or equal to 2", "path": "/minString"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedLengthMaxString", + documentation: """ + When a string member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "maxString" : "abcdefghijklmnopqrstuvwxyz" }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length 26 at '/maxString' failed to satisfy constraint: Member must have length less than or equal to 8", + "fieldList" : [{"message": "Value with length 26 at '/maxString' failed to satisfy constraint: Member must have length less than or equal to 8", "path": "/maxString"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedLengthList", + documentation: """ + When a list member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "list" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/list' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/list' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", "path": "/list"}]}""" + } + } + }, + testParameters: { + value: [ "[\"abc\"]", + "[\"abc\", \"abc\", \"abc\", \"abc\", \"abc\", \"abc\", \"abc\", \"abc\", \"abc\", \"abc\"]"], + inputLength: ["1", "10"] + } + }, + { + id: "RestJsonMalformedLengthListValue", + documentation: """ + When a list member's value does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "list" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/list/0' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/list/0' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", "path": "/list/0"}]}""" + } + } + }, + testParameters: { + value: [ "[\"a\", \"abc\"]", + "[\"abcdefghijklmnopqrstuvwxyz\", \"abc\"]" ], + inputLength: ["1", "26"] + } + }, + + // A valid map has 2-8 keys of length 2-8 that point to lists of length 2-8 with string values of length 2-8 + { + id: "RestJsonMalformedLengthMap", + documentation: """ + When a map member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "map" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/map' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/map' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", "path": "/map"}]}""" + } + } + }, + testParameters: { + value: [ "{\"abc\": [\"def\", \"efg\", \"fgh\"]}", + """ + {"abc": ["abc", "def", "efg"], "bcd": ["abc", "def", "efg"], + "cde": ["abc", "def", "efg"], "def": ["abc", "def", "efg"], + "efg": ["abc", "def", "efg"], "fgh": ["abc", "def", "efg"], + "ghi": ["abc", "def", "efg"], "jkl": ["abc", "def", "efg"], + "klm": ["abc", "def", "efg"], "lmn": ["abc", "def", "efg"] }"""], + inputLength: ["1", "10"] + } + }, + { + id: "RestJsonMalformedLengthMapKey", + documentation: """ + When a map member's key does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "map" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/map' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/map' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", "path": "/map"}]}""" + } + } + }, + testParameters: { + value: [ "{\"a\": [\"abc\", \"def\", \"efg\"], \"bcd\": [\"abc\", \"def\", \"efg\"], \"cde\": [\"abc\", \"def\", \"efg\"]}", + "{\"abcdefghijklmnopqrstuvwxyz\": [\"abc\", \"def\", \"efg\"], \"bcd\": [\"abc\", \"def\", \"efg\"], \"cde\": [\"abc\", \"def\", \"efg\"]}" ], + inputLength: ["1", "26"] + } + }, + { + id: "RestJsonMalformedLengthMapValue", + documentation: """ + When a map member's value does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLength", + body: """ + { "map" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/map/abc' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/map/abc' failed to satisfy constraint: Member must have length between 2 and 8, inclusive", "path": "/map/abc"}]}""" + } + } + }, + testParameters: { + value: [ "{\"abc\": [\"def\"], \"bcd\": [\"abc\", \"def\", \"efg\"], \"cde\": [\"abc\", \"def\", \"efg\"]}", + """ + {"abc": ["def", "efg", "fgh", "def", "efg", "fgh", "def", "efg", "fgh", "def"], + "bcd": ["abc", "def", "efg"], + "cde": ["abc", "def", "efg"]}""" ], + inputLength: ["1", "10"] + } + }, +]) + +// now repeat the above tests, but for the more specific constraints applied to the input member +apply MalformedLengthOverride @httpMalformedRequestTests([ + { + id: "RestJsonMalformedLengthBlobOverride", + documentation: """ + When a blob member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLengthOverride", + body: """ + { "blob" : $value:S }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/blob' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/blob' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", "path": "/blob"}]}""" + } + } + }, + testParameters: { + value: ["YWJj", "YWJjZGVmZw==="], + inputLength: ["3", "7"] + } + }, + { + id: "RestJsonMalformedLengthStringOverride", + documentation: """ + When a string member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLengthOverride", + body: """ + { "string" : $value:S }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/string' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/string' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", "path": "/string"}]}""" + } + } + }, + testParameters: { + value: ["abc", "abcdefg"], + inputLength: ["3", "7"] + } + }, + { + id: "RestJsonMalformedLengthMinStringOverride", + documentation: """ + When a string member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLengthOverride", + body: """ + { "minString" : "abc" }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length 3 at '/minString' failed to satisfy constraint: Member must have length greater than or equal to 4", + "fieldList" : [{"message": "Value with length 3 at '/minString' failed to satisfy constraint: Member must have length greater than or equal to 4", "path": "/minString"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedLengthMaxStringOverride", + documentation: """ + When a string member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLengthOverride", + body: """ + { "maxString" : "abcdefg" }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length 7 at '/maxString' failed to satisfy constraint: Member must have length less than or equal to 6", + "fieldList" : [{"message": "Value with length 7 at '/maxString' failed to satisfy constraint: Member must have length less than or equal to 6", "path": "/maxString"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedLengthListOverride", + documentation: """ + When a list member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLengthOverride", + body: """ + { "list" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/list' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/list' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", "path": "/list"}]}""" + } + } + }, + testParameters: { + value: [ "[\"abc\", \"def\", \"ghi\"]", + "[\"abc\", \"abc\", \"abc\", \"abc\", \"abc\", \"abc\", \"abc\"]"], + inputLength: ["3", "7"] + } + }, + + // A valid map has 4-6 keys of length 2-8 that point to lists of length 2-8 with string values of length 2-8 + { + id: "RestJsonMalformedLengthMapOverride", + documentation: """ + When a map member does not fit within length bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedLengthOverride", + body: """ + { "map" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value with length $inputLength:L at '/map' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", + "fieldList" : [{"message": "Value with length $inputLength:L at '/map' failed to satisfy constraint: Member must have length between 4 and 6, inclusive", "path": "/map"}]}""" + } + } + }, + testParameters: { + value: [ "{\"abc\": [\"def\", \"efg\", \"fgh\"], \"bcd\": [\"abc\", \"def\", \"efg\"], \"def\": [\"abc\", \"def\", \"efg\"]}", + """ + {"abc\": ["abc", "def", "efg"], "bcd": ["abc", "def", "efg"], + "cde\": ["abc", "def", "efg"], "def": ["abc", "def", "efg"], + "efg\": ["abc", "def", "efg"], "fgh": ["abc", "def", "efg"], + "ghi\": ["abc", "def", "efg"] }"""], + inputLength: ["3", "7"] + } + } +]) + +structure MalformedLengthInput { + blob: LengthBlob, + string: LengthString, + minString: MinLengthString, + maxString: MaxLengthString, + list: LengthList, + map: LengthMap +} + +structure MalformedLengthOverrideInput { + @length(min:4, max:6) + blob: LengthBlob, + + @length(min:4, max:6) + string: LengthString, + + @length(min:4) + minString: MinLengthString, + + @length(max:6) + maxString: MaxLengthString, + + @length(min:4, max:6) + list: LengthList, + + @length(min:4, max:6) + map: LengthMap +} + +@length(min:2, max:8) +blob LengthBlob + +@length(min:2, max:8) +string LengthString + +@length(min:2) +string MinLengthString + +@length(max:8) +string MaxLengthString + +@length(min:2, max:8) +list LengthList { + member: LengthString +} + +@length(min:2, max:8) +map LengthMap { + key: LengthString, + value: LengthList +} diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/malformed-pattern.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-pattern.smithy new file mode 100644 index 00000000000..3c851724463 --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-pattern.smithy @@ -0,0 +1,451 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.protocols#restJson1 +use smithy.test#httpMalformedRequestTests +use smithy.framework#ValidationException + +@http(uri: "/MalformedPattern", method: "POST") +operation MalformedPattern { + input: MalformedPatternInput, + errors: [ValidationException] +} + +@http(uri: "/MalformedPatternOverride", method: "POST") +operation MalformedPatternOverride { + input: MalformedPatternOverrideInput, + errors: [ValidationException] +} + +apply MalformedPattern @httpMalformedRequestTests([ + { + id: "RestJsonMalformedPatternString", + documentation: """ + When a string member does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPattern", + body: """ + { "string" : $value:S }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", "path": "/string"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternReDOSString", + documentation: """ + When the specified pattern is susceptible to ReDOS, the service will not + hang indefinitely while evaluating the pattern""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPattern", + body: """ + { "evilString" : "000000000000000000000000000000000000000000000000000000000000000000000000000000000000!" }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", "path": "/string"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedPatternList", + documentation: """ + When a list member value does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPattern", + body: """ + { "list" : [$value:S] }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/list/0' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/list/0' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", "path": "/list/0"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternMapKey", + documentation: """ + When a map member's key does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPattern", + body: """ + { "map" : { $value:S : "abc" } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/map' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/map' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", "path": "/map"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternMapValue", + documentation: """ + When a map member's value does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPattern", + body: """ + { "map" : { "abc": $value:S } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/map/abc' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/map/abc' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", "path": "/map/abc"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternUnion", + documentation: """ + When a union member's value does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPattern", + body: """ + { "union" : { "first": $value:S } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/union/first' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/union/first' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$$", "path": "/union/first"}]}""" + } + } + }, + testParameters: { + value: ["ABC", "xyz"] + } + }, +]) + + + +apply MalformedPatternOverride @httpMalformedRequestTests([ + { + id: "RestJsonMalformedPatternStringOverride", + documentation: """ + When a string member does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPatternOverride", + body: """ + { "string" : $value:S }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", "path": "/string"}]}""" + } + } + }, + testParameters: { + value: ["abc", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternListOverride", + documentation: """ + When a list member value does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPatternOverride", + body: """ + { "list" : [$value:S] }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/list/0' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/list/0' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", "path": "/list/0"}]}""" + } + } + }, + testParameters: { + value: ["abc", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternMapKeyOverride", + documentation: """ + When a map member's key does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPatternOverride", + body: """ + { "map" : { $value:S : "ghi" } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/map' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/map' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", "path": "/map"}]}""" + } + } + }, + testParameters: { + value: ["abc", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternMapValueOverride", + documentation: """ + When a map member's value does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPatternOverride", + body: """ + { "map" : { "ghi": $value:S } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/map/ghi' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/map/ghi' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", "path": "/map/ghi"}]}""" + } + } + }, + testParameters: { + value: ["abc", "xyz"] + } + }, + { + id: "RestJsonMalformedPatternUnionOverride", + documentation: """ + When a union member's value does not match the specified pattern, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedPatternOverride", + body: """ + { "union" : { "first": $value:S } }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/union/first' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", + "fieldList" : [{"message": "Value $value:L at '/union/first' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[g-m]+$$", "path": "/union/first"}]}""" + } + } + }, + testParameters: { + value: ["abc", "xyz"] + } + }, +]) + +structure MalformedPatternInput { + string: PatternString, + + evilString: EvilString, + + list: PatternList, + + map: PatternMap, + + union: PatternUnion +} + +structure MalformedPatternOverrideInput { + @pattern("^[g-m]+$") + string: PatternString, + + list: PatternListOverride, + + map: PatternMapOverride, + + union: PatternUnionOverride +} + +@pattern("^[a-m]+$") +string PatternString + +@pattern("^([0-9]+)+$") +string EvilString + +list PatternList { + member: PatternString +} + +list PatternListOverride { + @pattern("^[g-m]+$") + member: PatternString +} + +map PatternMap { + key: PatternString, + value: PatternString +} + +map PatternMapOverride { + @pattern("^[g-m]+$") + key: PatternString, + + @pattern("^[g-m]+$") + value: PatternString +} + +union PatternUnion { + first: PatternString, + second: PatternString +} + +union PatternUnionOverride { + @pattern("^[g-m]+$") + first: PatternString, + + @pattern("^[g-m]+$") + second: PatternString +} diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/malformed-range.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-range.smithy new file mode 100644 index 00000000000..4d927bbfaa0 --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-range.smithy @@ -0,0 +1,439 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.protocols#restJson1 +use smithy.test#httpMalformedRequestTests +use smithy.framework#ValidationException + +@http(uri: "/MalformedRange", method: "POST") +operation MalformedRange { + input: MalformedRangeInput, + errors: [ValidationException] +} + +@http(uri: "/MalformedRangeOverride", method: "POST") +operation MalformedRangeOverride { + input: MalformedRangeOverrideInput, + errors: [ValidationException] +} + +apply MalformedRange @httpMalformedRequestTests([ + { + id: "RestJsonMalformedRangeByte", + documentation: """ + When a byte member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRange", + body: """ + { "byte" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/byte' failed to satisfy constraint: Member must be between 2 and 8, inclusive", + "fieldList" : [{"message": "Value $value:L at '/byte' failed to satisfy constraint: Member must be between 2 and 8, inclusive", "path": "/byte"}]}""" + } + } + }, + testParameters: { + value: ["1", "9"] + } + }, + { + id: "RestJsonMalformedRangeMinByte", + documentation: """ + When a byte member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRange", + body: """ + { "minByte" : 1 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 1 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 2", + "fieldList" : [{"message": "Value 1 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 2", "path": "/minByte"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRangeMaxByte", + documentation: """ + When a byte member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRange", + body: """ + { "maxByte" : 9 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 9 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 8", + "fieldList" : [{"message": "Value 9 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 8", "path": "/maxByte"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRangeFloat", + documentation: """ + When a float member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRange", + body: """ + { "float" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/float' failed to satisfy constraint: Member must be between 2.2 and 8.8, inclusive", + "fieldList" : [{"message": "Value $value:L at '/float' failed to satisfy constraint: Member must be between 2.2 and 8.8, inclusive", "path": "/float"}]}""" + } + } + }, + testParameters: { + value: ["2.1", "8.9"] + } + }, + { + id: "RestJsonMalformedRangeMinFloat", + documentation: """ + When a float member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRange", + body: """ + { "minFloat" : 2.1 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 2.1 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 2.2", + "fieldList" : [{"message": "Value 2.1 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 2.2", "path": "/minFloat"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRangeMaxFloat", + documentation: """ + When a float member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRange", + body: """ + { "maxFloat" : 8.9 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 8.9 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 8.8", + "fieldList" : [{"message": "Value 8.9 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 8.8", "path": "/maxFloat"}]}""" + } + } + } + }, +]) + +// now repeat the above tests, but for the more specific constraints applied to the input member +apply MalformedRangeOverride @httpMalformedRequestTests([ + { + id: "RestJsonMalformedRangeByteOverride", + documentation: """ + When a byte member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRangeOverride", + body: """ + { "byte" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive", + "fieldList" : [{"message": "Value $value:L at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive", "path": "/byte"}]}""" + } + } + }, + testParameters: { + value: ["3", "7"] + } + }, + { + id: "RestJsonMalformedRangeMinByteOverride", + documentation: """ + When a byte member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRangeOverride", + body: """ + { "minByte" : 3 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 3 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 4", + "fieldList" : [{"message": "Value 3 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 4", "path": "/minByte"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRangeMaxByteOverride", + documentation: """ + When a byte member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRangeOverride", + body: """ + { "maxByte" : 7 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 7 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 6", + "fieldList" : [{"message": "Value 7 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 6", "path": "/maxByte"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRangeFloatOverride", + documentation: """ + When a float member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRangeOverride", + body: """ + { "float" : $value:L }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value $value:L at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive", + "fieldList" : [{"message": "Value $value:L at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive", "path": "/float"}]}""" + } + } + }, + testParameters: { + value: ["4.3", "6.7"] + } + }, + { + id: "RestJsonMalformedRangeMinFloatOverride", + documentation: """ + When a float member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRangeOverride", + body: """ + { "minFloat" : 4.3 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 4.3 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 4.4", + "fieldList" : [{"message": "Value 4.3 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 4.4", "path": "/minFloat"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRangeMaxFloatOverride", + documentation: """ + When a float member does not fit within range bounds, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRangeOverride", + body: """ + { "maxFloat" : 6.7 }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value 6.7 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 6.6", + "fieldList" : [{"message": "Value 6.7 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 6.6", "path": "/maxFloat"}]}""" + } + } + } + }, +]) + +structure MalformedRangeInput { + byte: RangeByte, + minByte: MinByte, + maxByte: MaxByte, + + float: RangeFloat, + minFloat: MinFloat, + maxFloat: MaxFloat, +} + +structure MalformedRangeOverrideInput { + @range(min:4, max:6) + byte: RangeByte, + @range(min:4) + minByte: MinByte, + @range(max:6) + maxByte: MaxByte, + + @range(min:4.4, max:6.6) + float: RangeFloat, + @range(min:4.4) + minFloat: MinFloat, + @range(max:6.6) + maxFloat: MaxFloat, +} + +@range(min:2, max:8) +byte RangeByte +@range(min:2) +byte MinByte +@range(max:8) +byte MaxByte + +@range(min:2.2, max:8.8) +float RangeFloat +@range(min:2.2) +float MinFloat +@range(max:8.8) +float MaxFloat + diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/malformed-required.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-required.smithy new file mode 100644 index 00000000000..2c0548d670c --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/malformed-required.smithy @@ -0,0 +1,165 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.protocols#restJson1 +use smithy.test#httpMalformedRequestTests +use smithy.framework#ValidationException + +@http(uri: "/MalformedRequired", method: "POST") +operation MalformedRequired { + input: MalformedRequiredInput, + errors: [ValidationException] +} + +apply MalformedRequired @httpMalformedRequestTests([ + { + id: "RestJsonMalformedRequiredBodyUnset", + documentation: """ + When a required member is not set in the message body, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRequired", + body: """ + { }""", + queryParams: [ + "stringInQuery=abc" + ], + headers: { + "content-type": "application/json", + "string-in-headers": "abc" + + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value null at '/string' failed to satisfy constraint: Member must not be null", + "fieldList" : [{"message": "Value null at '/string' failed to satisfy constraint: Member must not be null", "path": "/string"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRequiredBodyExplicitNull", + documentation: """ + When a required member is set to null in the message body, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRequired", + body: """ + { "string": null }""", + queryParams: [ + "stringInQuery=abc" + ], + headers: { + "content-type": "application/json", + "string-in-headers": "abc" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value null at '/string' failed to satisfy constraint: Member must not be null", + "fieldList" : [{"message": "Value null at '/string' failed to satisfy constraint: Member must not be null", "path": "/string"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRequiredQueryNoValue", + documentation: """ + When a required member has no value in the query string, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRequired", + body: """ + { "string": "abc" }""", + queryParams: [ + "stringInQuery" + ], + headers: { + "content-type": "application/json", + "string-in-headers": "abc" + }, + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value null at '/string' failed to satisfy constraint: Member must not be null", + "fieldList" : [{"message": "Value null at '/string' failed to satisfy constraint: Member must not be null", "path": "/string"}]}""" + } + } + } + }, + { + id: "RestJsonMalformedRequiredHeaderUnset", + documentation: """ + When a required member is not set in headers, + the response should be a 400 ValidationException.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/MalformedRequired", + body: """ + { "string": "abc" }""", + queryParams: [ + "stringInQuery=abc" + ], + headers: { + "content-type": "application/json" + }, + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value null at '/stringInHeader' failed to satisfy constraint: Member must not be null", + "fieldList" : [{"message": "Value null at '/stringInHeader' failed to satisfy constraint: Member must not be null", "path": "/stringInHeader"}]}""" + } + } + } + } +]) + +structure MalformedRequiredInput { + @required + string: String, + + @required + @httpQuery("stringInQuery") + stringInQuery: String, + + @required + @httpHeader("string-in-headers") + stringInHeader: String +} diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/recursive-structures.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/recursive-structures.smithy new file mode 100644 index 00000000000..b0edee46b0b --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/recursive-structures.smithy @@ -0,0 +1,98 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.protocols#restJson1 +use smithy.test#httpMalformedRequestTests +use smithy.test#httpRequestTests +use smithy.framework#ValidationException + +@http(uri: "/RecursiveStructures", method: "POST") +operation RecursiveStructures { + input: RecursiveStructuresInput, + errors: [ValidationException] +} + +apply RecursiveStructures @httpRequestTests([ + { + id: "RestJsonRecursiveStructuresValidate", + documentation: """ + Validation should work with recursive structures.""", + protocol: restJson1, + params: { + "union" : { + "union" : { + "union" : { "string" : "abc" } + } + } + }, + method: "POST", + uri: "/RecursiveStructures", + headers: { + "content-type": "application/json" + }, + body: """ + { "union" : { + "union" : { + "union" : { "string" : "abc" } + } + } + }""", + bodyMediaType: "application/json" + } +]) + +apply RecursiveStructures @httpMalformedRequestTests([ + { + id: "RestJsonMalformedRecursiveStructures", + documentation: """ + When a value deeply nested in a recursive structure does not meet constraints, + a 400 ValidationException is returned.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/RecursiveStructures", + body: """ + { "union" : { + "union" : { + "union" : { "string" : "XYZ" } + } + } + }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value XYZ at '/union/union/union/string' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", + "fieldList" : [{"message": "Value XYZ at '/union/union/union/string' failed to satisfy constraint: Member must satisfy enum value set: [abc, def]", "path": "/union/union/union/string"}]}""" + } + } + } + }, +]) + +structure RecursiveStructuresInput { + union: RecursiveUnionOne +} + +@enum([{value: "abc", name: "ABC"}, {value: "def", name: "DEF"}]) +string RecursiveEnumString + +union RecursiveUnionOne { + string: RecursiveEnumString, + union: RecursiveUnionTwo +} + +union RecursiveUnionTwo { + string: RecursiveEnumString, + union: RecursiveUnionOne +} diff --git a/smithy-aws-protocol-tests/model/restJson1/validation/sensitive-validation.smithy b/smithy-aws-protocol-tests/model/restJson1/validation/sensitive-validation.smithy new file mode 100644 index 00000000000..a028a646aca --- /dev/null +++ b/smithy-aws-protocol-tests/model/restJson1/validation/sensitive-validation.smithy @@ -0,0 +1,51 @@ +$version: "1.0" + +namespace aws.protocoltests.restjson.validation + +use aws.protocols#restJson1 +use smithy.test#httpMalformedRequestTests +use smithy.framework#ValidationException + +@http(uri: "/SensitiveValidation", method: "POST") +operation SensitiveValidation { + input: SensitiveValidationInput, + errors: [ValidationException] +} + +apply SensitiveValidation @httpMalformedRequestTests([ + { + id: "RestJsonMalformedPatternSensitiveString", + documentation: """ + When a sensitive member fails validation, the resultant + ValidationException will omit the value of the input.""", + protocol: restJson1, + request: { + method: "POST", + uri: "/SensitiveValidation", + body: """ + { "string" : "ABC" }""", + headers: { + "content-type": "application/json" + } + }, + response: { + code: 400, + headers: { + "x-amzn-errortype": "ValidationException" + }, + body: { + mediaType: "application/json", + assertion: { + contents: """ + { "message" : "1 validation error detected. Value at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$", + "fieldList" : [{"message": "Value at '/string' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-m]+$", "path": "/string"}]}""" + } + } + } + }, +]) + +structure SensitiveValidationInput { + @sensitive + string: PatternString +}