From baa4447e926a969a69a8faba52c0acf46c827ef3 Mon Sep 17 00:00:00 2001 From: Isaiah Vita <82135527+isaiahvita@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:30:07 -0800 Subject: [PATCH] Smithy upgrade (#2407) --- .../225527fb002548209347a0fdb79f6dca.json | 11 + codegen/gradle.properties | 2 +- .../aws/go/codegen/AwsProtocolUtils.java | 31 + .../api_op_HttpEnumPayload_test.go | 4 +- .../api_op_HttpStringPayload_test.go | 4 +- .../jsonrpc10/api_op_OperationWithDefaults.go | 163 +++ .../api_op_OperationWithDefaults_test.go | 409 ++++++ .../api_op_OperationWithNestedStructure.go | 134 ++ ...pi_op_OperationWithNestedStructure_test.go | 362 +++++ .../api_op_OperationWithRequiredMembers.go | 156 ++ ...pi_op_OperationWithRequiredMembers_test.go | 126 ++ .../protocoltest/jsonrpc10/deserializers.go | 1292 ++++++++++++++++- .../protocoltest/jsonrpc10/document/doc.go | 66 + .../jsonrpc10/document/document.go | 34 + .../protocoltest/jsonrpc10/generated.json | 10 + .../jsonrpc10/internal/document/document.go | 99 ++ .../internal/document/document_test.go | 11 + .../protocoltest/jsonrpc10/serializers.go | 465 ++++++ .../protocoltest/jsonrpc10/types/enums.go | 28 + .../protocoltest/jsonrpc10/types/types.go | 71 + internal/protocoltest/jsonrpc10/validators.go | 59 + .../restxml/api_op_HttpEnumPayload.go | 123 ++ .../restxml/api_op_HttpEnumPayload_test.go | 202 +++ .../restxml/api_op_HttpStringPayload.go | 122 ++ .../restxml/api_op_HttpStringPayload_test.go | 202 +++ .../protocoltest/restxml/deserializers.go | 180 +++ internal/protocoltest/restxml/generated.json | 4 + internal/protocoltest/restxml/serializers.go | 128 ++ internal/protocoltest/restxml/types/enums.go | 16 + 29 files changed, 4438 insertions(+), 76 deletions(-) create mode 100644 .changelog/225527fb002548209347a0fdb79f6dca.json create mode 100644 internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults.go create mode 100644 internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults_test.go create mode 100644 internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure.go create mode 100644 internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure_test.go create mode 100644 internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers.go create mode 100644 internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers_test.go create mode 100644 internal/protocoltest/jsonrpc10/document/doc.go create mode 100644 internal/protocoltest/jsonrpc10/document/document.go create mode 100644 internal/protocoltest/jsonrpc10/internal/document/document.go create mode 100644 internal/protocoltest/jsonrpc10/internal/document/document_test.go create mode 100644 internal/protocoltest/restxml/api_op_HttpEnumPayload.go create mode 100644 internal/protocoltest/restxml/api_op_HttpEnumPayload_test.go create mode 100644 internal/protocoltest/restxml/api_op_HttpStringPayload.go create mode 100644 internal/protocoltest/restxml/api_op_HttpStringPayload_test.go diff --git a/.changelog/225527fb002548209347a0fdb79f6dca.json b/.changelog/225527fb002548209347a0fdb79f6dca.json new file mode 100644 index 00000000000..8a44ac988cf --- /dev/null +++ b/.changelog/225527fb002548209347a0fdb79f6dca.json @@ -0,0 +1,11 @@ +{ + "id": "225527fb-0025-4820-9347-a0fdb79f6dca", + "type": "feature", + "description": "Upgrade smithy core", + "modules": [ + "internal/protocoltest/awsrestjson", + "internal/protocoltest/jsonrpc10", + "internal/protocoltest/restxml", + "service/internal/integrationtest" + ] +} \ No newline at end of file diff --git a/codegen/gradle.properties b/codegen/gradle.properties index 3f06b8d01fe..3c7e35179e0 100644 --- a/codegen/gradle.properties +++ b/codegen/gradle.properties @@ -1,2 +1,2 @@ -smithyVersion=1.39.0 +smithyVersion=1.41.1 smithyGradleVersion=0.7.0 diff --git a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/AwsProtocolUtils.java b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/AwsProtocolUtils.java index a6d5017114e..c25a8f27557 100644 --- a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/AwsProtocolUtils.java +++ b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/AwsProtocolUtils.java @@ -148,6 +148,20 @@ static void generateHttpProtocolTests(GenerationContext context) { .operation(ShapeId.from("aws.protocoltests.restxml#HttpPayloadWithUnion")) .addTestName("RestXmlHttpPayloadWithUnion") .addTestName("RestXmlHttpPayloadWithUnsetUnion") + .build(), + + + HttpProtocolUnitTestGenerator.SkipTest.builder() + .service(ShapeId.from("aws.protocoltests.json10#JsonRpc10")) + .operation(ShapeId.from("aws.protocoltests.json10#OperationWithDefaults")) + .addTestName("AwsJson10ClientPopulatesDefaultValuesInInput") + .addTestName("AwsJson10ClientSkipsTopLevelDefaultValuesInInput") + .addTestName("AwsJson10ClientUsesExplicitlyProvidedMemberValuesOverDefaults") + .build(), + HttpProtocolUnitTestGenerator.SkipTest.builder() + .service(ShapeId.from("aws.protocoltests.json10#JsonRpc10")) + .operation(ShapeId.from("aws.protocoltests.json10#OperationWithNestedStructure")) + .addTestName("AwsJson10ClientPopulatesNestedDefaultValuesWhenMissing") .build() )); @@ -180,6 +194,23 @@ static void generateHttpProtocolTests(GenerationContext context) { .service(ShapeId.from("aws.protocoltests.json#JsonProtocol")) .operation(ShapeId.from("aws.protocoltests.json#JsonUnions")) .addTestName("AwsJson11DeserializeIgnoreType") + .build(), + + HttpProtocolUnitTestGenerator.SkipTest.builder() + .service(ShapeId.from("aws.protocoltests.json10#JsonRpc10")) + .operation(ShapeId.from("aws.protocoltests.json10#OperationWithDefaults")) + .addTestName("AwsJson10ClientPopulatesDefaultsValuesWhenMissingInResponse") + .addTestName("AwsJson10ClientIgnoresDefaultValuesIfMemberValuesArePresentInResponse") + .build(), + HttpProtocolUnitTestGenerator.SkipTest.builder() + .service(ShapeId.from("aws.protocoltests.json10#JsonRpc10")) + .operation(ShapeId.from("aws.protocoltests.json10#OperationWithNestedStructure")) + .addTestName("AwsJson10ClientPopulatesNestedDefaultsWhenMissingInResponseBody") + .build(), + HttpProtocolUnitTestGenerator.SkipTest.builder() + .service(ShapeId.from("aws.protocoltests.json10#JsonRpc10")) + .operation(ShapeId.from("aws.protocoltests.json10#OperationWithRequiredMembers")) + .addTestName("AwsJson10ClientErrorCorrectsWhenServerFailsToSerializeRequiredValues") .build() )); diff --git a/internal/protocoltest/awsrestjson/api_op_HttpEnumPayload_test.go b/internal/protocoltest/awsrestjson/api_op_HttpEnumPayload_test.go index ef2faa578c2..4586ca0f1c8 100644 --- a/internal/protocoltest/awsrestjson/api_op_HttpEnumPayload_test.go +++ b/internal/protocoltest/awsrestjson/api_op_HttpEnumPayload_test.go @@ -39,7 +39,7 @@ func TestClient_HttpEnumPayload_awsRestjson1Serialize(t *testing.T) { BodyMediaType string BodyAssert func(io.Reader) error }{ - "EnumPayloadRequest": { + "RestJsonEnumPayloadRequest": { Params: &HttpEnumPayloadInput{ Payload: types.StringEnum("enumvalue"), }, @@ -123,7 +123,7 @@ func TestClient_HttpEnumPayload_awsRestjson1Deserialize(t *testing.T) { Body []byte ExpectResult *HttpEnumPayloadOutput }{ - "EnumPayloadResponse": { + "RestJsonEnumPayloadResponse": { StatusCode: 200, Body: []byte(`enumvalue`), ExpectResult: &HttpEnumPayloadOutput{ diff --git a/internal/protocoltest/awsrestjson/api_op_HttpStringPayload_test.go b/internal/protocoltest/awsrestjson/api_op_HttpStringPayload_test.go index 5e22268b736..7b4b130e3a4 100644 --- a/internal/protocoltest/awsrestjson/api_op_HttpStringPayload_test.go +++ b/internal/protocoltest/awsrestjson/api_op_HttpStringPayload_test.go @@ -39,7 +39,7 @@ func TestClient_HttpStringPayload_awsRestjson1Serialize(t *testing.T) { BodyMediaType string BodyAssert func(io.Reader) error }{ - "StringPayloadRequest": { + "RestJsonStringPayloadRequest": { Params: &HttpStringPayloadInput{ Payload: ptr.String("rawstring"), }, @@ -123,7 +123,7 @@ func TestClient_HttpStringPayload_awsRestjson1Deserialize(t *testing.T) { Body []byte ExpectResult *HttpStringPayloadOutput }{ - "StringPayloadResponse": { + "RestJsonStringPayloadResponse": { StatusCode: 200, Body: []byte(`rawstring`), ExpectResult: &HttpStringPayloadOutput{ diff --git a/internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults.go b/internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults.go new file mode 100644 index 00000000000..348a146660e --- /dev/null +++ b/internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults.go @@ -0,0 +1,163 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package jsonrpc10 + +import ( + "context" + "fmt" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/document" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/types" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" + "time" +) + +func (c *Client) OperationWithDefaults(ctx context.Context, params *OperationWithDefaultsInput, optFns ...func(*Options)) (*OperationWithDefaultsOutput, error) { + if params == nil { + params = &OperationWithDefaultsInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "OperationWithDefaults", params, optFns, c.addOperationOperationWithDefaultsMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*OperationWithDefaultsOutput) + out.ResultMetadata = metadata + return out, nil +} + +type OperationWithDefaultsInput struct { + Defaults *types.Defaults + + TopLevelDefault *string + + noSmithyDocumentSerde +} + +type OperationWithDefaultsOutput struct { + DefaultBlob []byte + + DefaultBoolean *bool + + DefaultByte *int8 + + DefaultDocumentBoolean document.Interface + + DefaultDocumentList document.Interface + + DefaultDocumentMap document.Interface + + DefaultDocumentString document.Interface + + DefaultDouble *float64 + + DefaultEnum types.TestEnum + + DefaultFloat *float32 + + DefaultIntEnum types.TestIntEnum + + DefaultInteger *int32 + + DefaultList []string + + DefaultLong *int64 + + DefaultMap map[string]string + + DefaultNullDocument document.Interface + + DefaultShort *int16 + + DefaultString *string + + DefaultTimestamp *time.Time + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationOperationWithDefaultsMiddlewares(stack *middleware.Stack, options Options) (err error) { + if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { + return err + } + err = stack.Serialize.Add(&awsAwsjson10_serializeOpOperationWithDefaults{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsAwsjson10_deserializeOpOperationWithDefaults{}, middleware.After) + if err != nil { + return err + } + if err := addProtocolFinalizerMiddlewares(stack, options, "OperationWithDefaults"); err != nil { + return fmt.Errorf("add protocol finalizers: %v", err) + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addSetLoggerMiddleware(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addRetryMiddlewares(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { + return err + } + if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { + return err + } + if err = addClientUserAgent(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware_opOperationWithDefaults(options.Region), middleware.Before); err != nil { + return err + } + if err = awsmiddleware.AddRecursionDetection(stack); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + return nil +} + +func newServiceMetadataMiddleware_opOperationWithDefaults(region string) *awsmiddleware.RegisterServiceMetadata { + return &awsmiddleware.RegisterServiceMetadata{ + Region: region, + ServiceID: ServiceID, + OperationName: "OperationWithDefaults", + } +} diff --git a/internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults_test.go b/internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults_test.go new file mode 100644 index 00000000000..c71fee421af --- /dev/null +++ b/internal/protocoltest/jsonrpc10/api_op_OperationWithDefaults_test.go @@ -0,0 +1,409 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package jsonrpc10 + +import ( + "bytes" + "context" + "github.com/aws/aws-sdk-go-v2/aws" + protocoltesthttp "github.com/aws/aws-sdk-go-v2/internal/protocoltest" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/document" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/types" + smithydocument "github.com/aws/smithy-go/document" + "github.com/aws/smithy-go/middleware" + smithyprivateprotocol "github.com/aws/smithy-go/private/protocol" + "github.com/aws/smithy-go/ptr" + smithytesting "github.com/aws/smithy-go/testing" + smithytime "github.com/aws/smithy-go/time" + smithyhttp "github.com/aws/smithy-go/transport/http" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "io" + "io/ioutil" + "math" + "net/http" + "net/url" + "testing" +) + +func TestClient_OperationWithDefaults_awsAwsjson10Serialize(t *testing.T) { + cases := map[string]struct { + Params *OperationWithDefaultsInput + ExpectMethod string + ExpectURIPath string + ExpectQuery []smithytesting.QueryItem + RequireQuery []string + ForbidQuery []string + ExpectHeader http.Header + RequireHeader []string + ForbidHeader []string + Host *url.URL + BodyMediaType string + BodyAssert func(io.Reader) error + }{ + // Client populates default values in input. + "AwsJson10ClientPopulatesDefaultValuesInInput": { + Params: &OperationWithDefaultsInput{ + Defaults: &types.Defaults{}, + }, + ExpectMethod: "POST", + ExpectURIPath: "/", + ExpectQuery: []smithytesting.QueryItem{}, + ExpectHeader: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + BodyAssert: func(actual io.Reader) error { + return smithytesting.CompareJSONReaderBytes(actual, []byte(`{ + "defaults": { + "defaultString": "hi", + "defaultBoolean": true, + "defaultList": [], + "defaultDocumentMap": {}, + "defaultDocumentString": "hi", + "defaultDocumentBoolean": true, + "defaultDocumentList": [], + "defaultTimestamp": 0, + "defaultBlob": "YWJj", + "defaultByte": 1, + "defaultShort": 1, + "defaultInteger": 10, + "defaultLong": 100, + "defaultFloat": 1.0, + "defaultDouble": 1.0, + "defaultMap": {}, + "defaultEnum": "FOO", + "defaultIntEnum": 1 + } + }`)) + }, + }, + // Client skips top level default values in input. + "AwsJson10ClientSkipsTopLevelDefaultValuesInInput": { + Params: &OperationWithDefaultsInput{}, + ExpectMethod: "POST", + ExpectURIPath: "/", + ExpectQuery: []smithytesting.QueryItem{}, + ExpectHeader: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + BodyAssert: func(actual io.Reader) error { + return smithytesting.CompareJSONReaderBytes(actual, []byte(`{ + }`)) + }, + }, + // Client uses explicitly provided member values over defaults + "AwsJson10ClientUsesExplicitlyProvidedMemberValuesOverDefaults": { + Params: &OperationWithDefaultsInput{ + Defaults: &types.Defaults{ + DefaultString: ptr.String("bye"), + DefaultBoolean: ptr.Bool(true), + DefaultList: []string{ + "a", + }, + DefaultDocumentMap: document.NewLazyDocument(map[string]interface{}{ + "name": "Jack", + }), + DefaultDocumentString: document.NewLazyDocument("bye"), + DefaultDocumentBoolean: document.NewLazyDocument(true), + DefaultDocumentList: document.NewLazyDocument([]interface{}{ + "b", + }), + DefaultNullDocument: document.NewLazyDocument("notNull"), + DefaultTimestamp: ptr.Time(smithytime.ParseEpochSeconds(1)), + DefaultBlob: []byte("hi"), + DefaultByte: ptr.Int8(2), + DefaultShort: ptr.Int16(2), + DefaultInteger: ptr.Int32(20), + DefaultLong: ptr.Int64(200), + DefaultFloat: ptr.Float32(2.0), + DefaultDouble: ptr.Float64(2.0), + DefaultMap: map[string]string{ + "name": "Jack", + }, + DefaultEnum: types.TestEnum("BAR"), + DefaultIntEnum: 2, + }, + }, + ExpectMethod: "POST", + ExpectURIPath: "/", + ExpectQuery: []smithytesting.QueryItem{}, + ExpectHeader: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + BodyAssert: func(actual io.Reader) error { + return smithytesting.CompareJSONReaderBytes(actual, []byte(`{ + "defaults": { + "defaultString": "bye", + "defaultBoolean": true, + "defaultList": ["a"], + "defaultDocumentMap": {"name": "Jack"}, + "defaultDocumentString": "bye", + "defaultDocumentBoolean": true, + "defaultDocumentList": ["b"], + "defaultNullDocument": "notNull", + "defaultTimestamp": 1, + "defaultBlob": "aGk=", + "defaultByte": 2, + "defaultShort": 2, + "defaultInteger": 20, + "defaultLong": 200, + "defaultFloat": 2.0, + "defaultDouble": 2.0, + "defaultMap": {"name": "Jack"}, + "defaultEnum": "BAR", + "defaultIntEnum": 2 + } + }`)) + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + if name == "AwsJson10ClientPopulatesDefaultValuesInInput" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithDefaults") + } + + if name == "AwsJson10ClientSkipsTopLevelDefaultValuesInInput" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithDefaults") + } + + if name == "AwsJson10ClientUsesExplicitlyProvidedMemberValuesOverDefaults" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithDefaults") + } + + actualReq := &http.Request{} + serverURL := "http://localhost:8888/" + if c.Host != nil { + u, err := url.Parse(serverURL) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + u.Path = c.Host.Path + u.RawPath = c.Host.RawPath + u.RawQuery = c.Host.RawQuery + serverURL = u.String() + } + client := New(Options{ + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + HTTPClient: protocoltesthttp.NewClient(), + Region: "us-west-2", + }) + result, err := client.OperationWithDefaults(context.Background(), c.Params, func(options *Options) { + options.APIOptions = append(options.APIOptions, func(stack *middleware.Stack) error { + return smithyprivateprotocol.AddCaptureRequestMiddleware(stack, actualReq) + }) + }) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + if e, a := c.ExpectMethod, actualReq.Method; e != a { + t.Errorf("expect %v method, got %v", e, a) + } + if e, a := c.ExpectURIPath, actualReq.URL.RawPath; e != a { + t.Errorf("expect %v path, got %v", e, a) + } + queryItems := smithytesting.ParseRawQuery(actualReq.URL.RawQuery) + smithytesting.AssertHasQuery(t, c.ExpectQuery, queryItems) + smithytesting.AssertHasQueryKeys(t, c.RequireQuery, queryItems) + smithytesting.AssertNotHaveQueryKeys(t, c.ForbidQuery, queryItems) + smithytesting.AssertHasHeader(t, c.ExpectHeader, actualReq.Header) + smithytesting.AssertHasHeaderKeys(t, c.RequireHeader, actualReq.Header) + smithytesting.AssertNotHaveHeaderKeys(t, c.ForbidHeader, actualReq.Header) + if c.BodyAssert != nil { + if err := c.BodyAssert(actualReq.Body); err != nil { + t.Errorf("expect body equal, got %v", err) + } + } + }) + } +} + +func TestClient_OperationWithDefaults_awsAwsjson10Deserialize(t *testing.T) { + cases := map[string]struct { + StatusCode int + Header http.Header + BodyMediaType string + Body []byte + ExpectResult *OperationWithDefaultsOutput + }{ + // Client populates default values when missing in response. + "AwsJson10ClientPopulatesDefaultsValuesWhenMissingInResponse": { + StatusCode: 200, + Header: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + Body: []byte(`{}`), + ExpectResult: &OperationWithDefaultsOutput{ + DefaultString: ptr.String("hi"), + DefaultBoolean: ptr.Bool(true), + DefaultList: []string{}, + DefaultDocumentMap: document.NewLazyDocument(map[string]interface{}{}), + DefaultDocumentString: document.NewLazyDocument("hi"), + DefaultDocumentBoolean: document.NewLazyDocument(true), + DefaultDocumentList: document.NewLazyDocument([]interface{}{}), + DefaultTimestamp: ptr.Time(smithytime.ParseEpochSeconds(0)), + DefaultBlob: []byte("abc"), + DefaultByte: ptr.Int8(1), + DefaultShort: ptr.Int16(1), + DefaultInteger: ptr.Int32(10), + DefaultLong: ptr.Int64(100), + DefaultFloat: ptr.Float32(1.0), + DefaultDouble: ptr.Float64(1.0), + DefaultMap: map[string]string{}, + DefaultEnum: types.TestEnum("FOO"), + DefaultIntEnum: 1, + }, + }, + // Client ignores default values if member values are present in the response. + "AwsJson10ClientIgnoresDefaultValuesIfMemberValuesArePresentInResponse": { + StatusCode: 200, + Header: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + Body: []byte(`{ + "defaultString": "bye", + "defaultBoolean": false, + "defaultList": ["a"], + "defaultDocumentMap": {"name": "Jack"}, + "defaultDocumentString": "bye", + "defaultDocumentBoolean": false, + "defaultDocumentList": ["b"], + "defaultNullDocument": "notNull", + "defaultTimestamp": 2, + "defaultBlob": "aGk=", + "defaultByte": 2, + "defaultShort": 2, + "defaultInteger": 20, + "defaultLong": 200, + "defaultFloat": 2.0, + "defaultDouble": 2.0, + "defaultMap": {"name": "Jack"}, + "defaultEnum": "BAR", + "defaultIntEnum": 2 + }`), + ExpectResult: &OperationWithDefaultsOutput{ + DefaultString: ptr.String("bye"), + DefaultBoolean: ptr.Bool(false), + DefaultList: []string{ + "a", + }, + DefaultDocumentMap: document.NewLazyDocument(map[string]interface{}{ + "name": "Jack", + }), + DefaultDocumentString: document.NewLazyDocument("bye"), + DefaultDocumentBoolean: document.NewLazyDocument(false), + DefaultDocumentList: document.NewLazyDocument([]interface{}{ + "b", + }), + DefaultNullDocument: document.NewLazyDocument("notNull"), + DefaultTimestamp: ptr.Time(smithytime.ParseEpochSeconds(2)), + DefaultBlob: []byte("hi"), + DefaultByte: ptr.Int8(2), + DefaultShort: ptr.Int16(2), + DefaultInteger: ptr.Int32(20), + DefaultLong: ptr.Int64(200), + DefaultFloat: ptr.Float32(2.0), + DefaultDouble: ptr.Float64(2.0), + DefaultMap: map[string]string{ + "name": "Jack", + }, + DefaultEnum: types.TestEnum("BAR"), + DefaultIntEnum: 2, + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + if name == "AwsJson10ClientPopulatesDefaultsValuesWhenMissingInResponse" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithDefaults") + } + + if name == "AwsJson10ClientIgnoresDefaultValuesIfMemberValuesArePresentInResponse" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithDefaults") + } + + serverURL := "http://localhost:8888/" + client := New(Options{ + HTTPClient: smithyhttp.ClientDoFunc(func(r *http.Request) (*http.Response, error) { + headers := http.Header{} + for k, vs := range c.Header { + for _, v := range vs { + headers.Add(k, v) + } + } + if len(c.BodyMediaType) != 0 && len(headers.Values("Content-Type")) == 0 { + headers.Set("Content-Type", c.BodyMediaType) + } + response := &http.Response{ + StatusCode: c.StatusCode, + Header: headers, + Request: r, + } + if len(c.Body) != 0 { + response.ContentLength = int64(len(c.Body)) + response.Body = ioutil.NopCloser(bytes.NewReader(c.Body)) + } else { + + response.Body = http.NoBody + } + return response, nil + }), + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + Region: "us-west-2", + }) + var params OperationWithDefaultsInput + result, err := client.OperationWithDefaults(context.Background(), ¶ms) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + opts := cmp.Options{ + cmpopts.IgnoreUnexported( + middleware.Metadata{}, + ), + cmp.FilterValues(func(x, y float64) bool { + return math.IsNaN(x) && math.IsNaN(y) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmp.FilterValues(func(x, y float32) bool { + return math.IsNaN(float64(x)) && math.IsNaN(float64(y)) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmpopts.IgnoreTypes(smithydocument.NoSerde{}), + } + if err := smithytesting.CompareValues(c.ExpectResult, result, opts...); err != nil { + t.Errorf("expect c.ExpectResult value match:\n%v", err) + } + }) + } +} diff --git a/internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure.go b/internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure.go new file mode 100644 index 00000000000..091da766d66 --- /dev/null +++ b/internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure.go @@ -0,0 +1,134 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package jsonrpc10 + +import ( + "context" + "fmt" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/types" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +func (c *Client) OperationWithNestedStructure(ctx context.Context, params *OperationWithNestedStructureInput, optFns ...func(*Options)) (*OperationWithNestedStructureOutput, error) { + if params == nil { + params = &OperationWithNestedStructureInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "OperationWithNestedStructure", params, optFns, c.addOperationOperationWithNestedStructureMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*OperationWithNestedStructureOutput) + out.ResultMetadata = metadata + return out, nil +} + +type OperationWithNestedStructureInput struct { + + // This member is required. + TopLevel *types.TopLevel + + noSmithyDocumentSerde +} + +type OperationWithNestedStructureOutput struct { + + // This member is required. + Dialog *types.Dialog + + DialogList []types.Dialog + + DialogMap map[string]types.Dialog + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationOperationWithNestedStructureMiddlewares(stack *middleware.Stack, options Options) (err error) { + if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { + return err + } + err = stack.Serialize.Add(&awsAwsjson10_serializeOpOperationWithNestedStructure{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsAwsjson10_deserializeOpOperationWithNestedStructure{}, middleware.After) + if err != nil { + return err + } + if err := addProtocolFinalizerMiddlewares(stack, options, "OperationWithNestedStructure"); err != nil { + return fmt.Errorf("add protocol finalizers: %v", err) + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addSetLoggerMiddleware(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addRetryMiddlewares(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { + return err + } + if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { + return err + } + if err = addClientUserAgent(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { + return err + } + if err = addOpOperationWithNestedStructureValidationMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware_opOperationWithNestedStructure(options.Region), middleware.Before); err != nil { + return err + } + if err = awsmiddleware.AddRecursionDetection(stack); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + return nil +} + +func newServiceMetadataMiddleware_opOperationWithNestedStructure(region string) *awsmiddleware.RegisterServiceMetadata { + return &awsmiddleware.RegisterServiceMetadata{ + Region: region, + ServiceID: ServiceID, + OperationName: "OperationWithNestedStructure", + } +} diff --git a/internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure_test.go b/internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure_test.go new file mode 100644 index 00000000000..3497e8ac1e1 --- /dev/null +++ b/internal/protocoltest/jsonrpc10/api_op_OperationWithNestedStructure_test.go @@ -0,0 +1,362 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package jsonrpc10 + +import ( + "bytes" + "context" + "github.com/aws/aws-sdk-go-v2/aws" + protocoltesthttp "github.com/aws/aws-sdk-go-v2/internal/protocoltest" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/types" + smithydocument "github.com/aws/smithy-go/document" + "github.com/aws/smithy-go/middleware" + smithyprivateprotocol "github.com/aws/smithy-go/private/protocol" + "github.com/aws/smithy-go/ptr" + smithytesting "github.com/aws/smithy-go/testing" + smithyhttp "github.com/aws/smithy-go/transport/http" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "io" + "io/ioutil" + "math" + "net/http" + "net/url" + "testing" +) + +func TestClient_OperationWithNestedStructure_awsAwsjson10Serialize(t *testing.T) { + cases := map[string]struct { + Params *OperationWithNestedStructureInput + ExpectMethod string + ExpectURIPath string + ExpectQuery []smithytesting.QueryItem + RequireQuery []string + ForbidQuery []string + ExpectHeader http.Header + RequireHeader []string + ForbidHeader []string + Host *url.URL + BodyMediaType string + BodyAssert func(io.Reader) error + }{ + // Client populates nested default values when missing. + "AwsJson10ClientPopulatesNestedDefaultValuesWhenMissing": { + Params: &OperationWithNestedStructureInput{ + TopLevel: &types.TopLevel{ + Dialog: &types.Dialog{ + Language: ptr.String("en"), + }, + DialogList: []types.Dialog{ + {}, + { + Farewell: &types.Farewell{}, + }, + { + Language: ptr.String("it"), + Greeting: ptr.String("ciao"), + Farewell: &types.Farewell{ + Phrase: ptr.String("arrivederci"), + }, + }, + }, + DialogMap: map[string]types.Dialog{ + "emptyDialog": {}, + "partialEmptyDialog": { + Language: ptr.String("en"), + Farewell: &types.Farewell{}, + }, + "nonEmptyDialog": { + Greeting: ptr.String("konnichiwa"), + Farewell: &types.Farewell{ + Phrase: ptr.String("sayonara"), + }, + }, + }, + }, + }, + ExpectMethod: "POST", + ExpectURIPath: "/", + ExpectQuery: []smithytesting.QueryItem{}, + ExpectHeader: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + BodyAssert: func(actual io.Reader) error { + return smithytesting.CompareJSONReaderBytes(actual, []byte(`{ + "topLevel": { + "dialog": { + "language": "en", + "greeting": "hi" + }, + "dialogList": [ + { + "greeting": "hi" + }, + { + "greeting": "hi", + "farewell": { + "phrase": "bye" + } + }, + { + "language": "it", + "greeting": "ciao", + "farewell": { + "phrase": "arrivederci" + } + } + ], + "dialogMap": { + "emptyDialog": { + "greeting": "hi" + }, + "partialEmptyDialog": { + "language": "en", + "greeting": "hi", + "farewell": { + "phrase": "bye" + } + }, + "nonEmptyDialog": { + "greeting": "konnichiwa", + "farewell": { + "phrase": "sayonara" + } + } + } + } + }`)) + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + if name == "AwsJson10ClientPopulatesNestedDefaultValuesWhenMissing" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithNestedStructure") + } + + actualReq := &http.Request{} + serverURL := "http://localhost:8888/" + if c.Host != nil { + u, err := url.Parse(serverURL) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + u.Path = c.Host.Path + u.RawPath = c.Host.RawPath + u.RawQuery = c.Host.RawQuery + serverURL = u.String() + } + client := New(Options{ + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + HTTPClient: protocoltesthttp.NewClient(), + Region: "us-west-2", + }) + result, err := client.OperationWithNestedStructure(context.Background(), c.Params, func(options *Options) { + options.APIOptions = append(options.APIOptions, func(stack *middleware.Stack) error { + return smithyprivateprotocol.AddCaptureRequestMiddleware(stack, actualReq) + }) + }) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + if e, a := c.ExpectMethod, actualReq.Method; e != a { + t.Errorf("expect %v method, got %v", e, a) + } + if e, a := c.ExpectURIPath, actualReq.URL.RawPath; e != a { + t.Errorf("expect %v path, got %v", e, a) + } + queryItems := smithytesting.ParseRawQuery(actualReq.URL.RawQuery) + smithytesting.AssertHasQuery(t, c.ExpectQuery, queryItems) + smithytesting.AssertHasQueryKeys(t, c.RequireQuery, queryItems) + smithytesting.AssertNotHaveQueryKeys(t, c.ForbidQuery, queryItems) + smithytesting.AssertHasHeader(t, c.ExpectHeader, actualReq.Header) + smithytesting.AssertHasHeaderKeys(t, c.RequireHeader, actualReq.Header) + smithytesting.AssertNotHaveHeaderKeys(t, c.ForbidHeader, actualReq.Header) + if c.BodyAssert != nil { + if err := c.BodyAssert(actualReq.Body); err != nil { + t.Errorf("expect body equal, got %v", err) + } + } + }) + } +} + +func TestClient_OperationWithNestedStructure_awsAwsjson10Deserialize(t *testing.T) { + cases := map[string]struct { + StatusCode int + Header http.Header + BodyMediaType string + Body []byte + ExpectResult *OperationWithNestedStructureOutput + }{ + // Client populates nested default values when missing in response body. + "AwsJson10ClientPopulatesNestedDefaultsWhenMissingInResponseBody": { + StatusCode: 200, + Header: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + Body: []byte(`{ + "dialog": { + "language": "en" + }, + "dialogList": [ + { + }, + { + "farewell": {} + }, + { + "language": "it", + "greeting": "ciao", + "farewell": { + "phrase": "arrivederci" + } + } + ], + "dialogMap": { + "emptyDialog": { + }, + "partialEmptyDialog": { + "language": "en", + "farewell": {} + }, + "nonEmptyDialog": { + "greeting": "konnichiwa", + "farewell": { + "phrase": "sayonara" + } + } + } + }`), + ExpectResult: &OperationWithNestedStructureOutput{ + Dialog: &types.Dialog{ + Language: ptr.String("en"), + Greeting: ptr.String("hi"), + }, + DialogList: []types.Dialog{ + { + Greeting: ptr.String("hi"), + }, + { + Greeting: ptr.String("hi"), + Farewell: &types.Farewell{ + Phrase: ptr.String("bye"), + }, + }, + { + Language: ptr.String("it"), + Greeting: ptr.String("ciao"), + Farewell: &types.Farewell{ + Phrase: ptr.String("arrivederci"), + }, + }, + }, + DialogMap: map[string]types.Dialog{ + "emptyDialog": { + Greeting: ptr.String("hi"), + }, + "partialEmptyDialog": { + Language: ptr.String("en"), + Greeting: ptr.String("hi"), + Farewell: &types.Farewell{ + Phrase: ptr.String("bye"), + }, + }, + "nonEmptyDialog": { + Greeting: ptr.String("konnichiwa"), + Farewell: &types.Farewell{ + Phrase: ptr.String("sayonara"), + }, + }, + }, + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + if name == "AwsJson10ClientPopulatesNestedDefaultsWhenMissingInResponseBody" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithNestedStructure") + } + + serverURL := "http://localhost:8888/" + client := New(Options{ + HTTPClient: smithyhttp.ClientDoFunc(func(r *http.Request) (*http.Response, error) { + headers := http.Header{} + for k, vs := range c.Header { + for _, v := range vs { + headers.Add(k, v) + } + } + if len(c.BodyMediaType) != 0 && len(headers.Values("Content-Type")) == 0 { + headers.Set("Content-Type", c.BodyMediaType) + } + response := &http.Response{ + StatusCode: c.StatusCode, + Header: headers, + Request: r, + } + if len(c.Body) != 0 { + response.ContentLength = int64(len(c.Body)) + response.Body = ioutil.NopCloser(bytes.NewReader(c.Body)) + } else { + + response.Body = http.NoBody + } + return response, nil + }), + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + Region: "us-west-2", + }) + var params OperationWithNestedStructureInput + result, err := client.OperationWithNestedStructure(context.Background(), ¶ms) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + opts := cmp.Options{ + cmpopts.IgnoreUnexported( + middleware.Metadata{}, + ), + cmp.FilterValues(func(x, y float64) bool { + return math.IsNaN(x) && math.IsNaN(y) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmp.FilterValues(func(x, y float32) bool { + return math.IsNaN(float64(x)) && math.IsNaN(float64(y)) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmpopts.IgnoreTypes(smithydocument.NoSerde{}), + } + if err := smithytesting.CompareValues(c.ExpectResult, result, opts...); err != nil { + t.Errorf("expect c.ExpectResult value match:\n%v", err) + } + }) + } +} diff --git a/internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers.go b/internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers.go new file mode 100644 index 00000000000..2d6166a07d7 --- /dev/null +++ b/internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers.go @@ -0,0 +1,156 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package jsonrpc10 + +import ( + "context" + "fmt" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" + "time" +) + +func (c *Client) OperationWithRequiredMembers(ctx context.Context, params *OperationWithRequiredMembersInput, optFns ...func(*Options)) (*OperationWithRequiredMembersOutput, error) { + if params == nil { + params = &OperationWithRequiredMembersInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "OperationWithRequiredMembers", params, optFns, c.addOperationOperationWithRequiredMembersMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*OperationWithRequiredMembersOutput) + out.ResultMetadata = metadata + return out, nil +} + +type OperationWithRequiredMembersInput struct { + noSmithyDocumentSerde +} + +type OperationWithRequiredMembersOutput struct { + + // This member is required. + RequiredBlob []byte + + // This member is required. + RequiredBoolean *bool + + // This member is required. + RequiredByte *int8 + + // This member is required. + RequiredDouble *float64 + + // This member is required. + RequiredFloat *float32 + + // This member is required. + RequiredInteger *int32 + + // This member is required. + RequiredList []string + + // This member is required. + RequiredLong *int64 + + // This member is required. + RequiredMap map[string]string + + // This member is required. + RequiredShort *int16 + + // This member is required. + RequiredString *string + + // This member is required. + RequiredTimestamp *time.Time + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationOperationWithRequiredMembersMiddlewares(stack *middleware.Stack, options Options) (err error) { + if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { + return err + } + err = stack.Serialize.Add(&awsAwsjson10_serializeOpOperationWithRequiredMembers{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsAwsjson10_deserializeOpOperationWithRequiredMembers{}, middleware.After) + if err != nil { + return err + } + if err := addProtocolFinalizerMiddlewares(stack, options, "OperationWithRequiredMembers"); err != nil { + return fmt.Errorf("add protocol finalizers: %v", err) + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addSetLoggerMiddleware(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addRetryMiddlewares(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { + return err + } + if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { + return err + } + if err = addClientUserAgent(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware_opOperationWithRequiredMembers(options.Region), middleware.Before); err != nil { + return err + } + if err = awsmiddleware.AddRecursionDetection(stack); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + return nil +} + +func newServiceMetadataMiddleware_opOperationWithRequiredMembers(region string) *awsmiddleware.RegisterServiceMetadata { + return &awsmiddleware.RegisterServiceMetadata{ + Region: region, + ServiceID: ServiceID, + OperationName: "OperationWithRequiredMembers", + } +} diff --git a/internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers_test.go b/internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers_test.go new file mode 100644 index 00000000000..e201e89c72a --- /dev/null +++ b/internal/protocoltest/jsonrpc10/api_op_OperationWithRequiredMembers_test.go @@ -0,0 +1,126 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package jsonrpc10 + +import ( + "bytes" + "context" + "github.com/aws/aws-sdk-go-v2/aws" + smithydocument "github.com/aws/smithy-go/document" + "github.com/aws/smithy-go/middleware" + "github.com/aws/smithy-go/ptr" + smithytesting "github.com/aws/smithy-go/testing" + smithytime "github.com/aws/smithy-go/time" + smithyhttp "github.com/aws/smithy-go/transport/http" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "io/ioutil" + "math" + "net/http" + "testing" +) + +func TestClient_OperationWithRequiredMembers_awsAwsjson10Deserialize(t *testing.T) { + cases := map[string]struct { + StatusCode int + Header http.Header + BodyMediaType string + Body []byte + ExpectResult *OperationWithRequiredMembersOutput + }{ + // Client error corrects when server fails to serialize required values. + "AwsJson10ClientErrorCorrectsWhenServerFailsToSerializeRequiredValues": { + StatusCode: 200, + Header: http.Header{ + "Content-Type": []string{"application/x-amz-json-1.0"}, + }, + BodyMediaType: "application/json", + Body: []byte(`{}`), + ExpectResult: &OperationWithRequiredMembersOutput{ + RequiredString: ptr.String(""), + RequiredBoolean: ptr.Bool(false), + RequiredList: []string{}, + RequiredTimestamp: ptr.Time(smithytime.ParseEpochSeconds(0)), + RequiredBlob: []byte(""), + RequiredByte: ptr.Int8(0), + RequiredShort: ptr.Int16(0), + RequiredInteger: ptr.Int32(0), + RequiredLong: ptr.Int64(0), + RequiredFloat: ptr.Float32(0.0), + RequiredDouble: ptr.Float64(0.0), + RequiredMap: map[string]string{}, + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + if name == "AwsJson10ClientErrorCorrectsWhenServerFailsToSerializeRequiredValues" { + t.Skip("disabled test aws.protocoltests.json10#JsonRpc10 aws.protocoltests.json10#OperationWithRequiredMembers") + } + + serverURL := "http://localhost:8888/" + client := New(Options{ + HTTPClient: smithyhttp.ClientDoFunc(func(r *http.Request) (*http.Response, error) { + headers := http.Header{} + for k, vs := range c.Header { + for _, v := range vs { + headers.Add(k, v) + } + } + if len(c.BodyMediaType) != 0 && len(headers.Values("Content-Type")) == 0 { + headers.Set("Content-Type", c.BodyMediaType) + } + response := &http.Response{ + StatusCode: c.StatusCode, + Header: headers, + Request: r, + } + if len(c.Body) != 0 { + response.ContentLength = int64(len(c.Body)) + response.Body = ioutil.NopCloser(bytes.NewReader(c.Body)) + } else { + + response.Body = http.NoBody + } + return response, nil + }), + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + Region: "us-west-2", + }) + var params OperationWithRequiredMembersInput + result, err := client.OperationWithRequiredMembers(context.Background(), ¶ms) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + opts := cmp.Options{ + cmpopts.IgnoreUnexported( + middleware.Metadata{}, + ), + cmp.FilterValues(func(x, y float64) bool { + return math.IsNaN(x) && math.IsNaN(y) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmp.FilterValues(func(x, y float32) bool { + return math.IsNaN(float64(x)) && math.IsNaN(float64(y)) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmpopts.IgnoreTypes(smithydocument.NoSerde{}), + } + if err := smithytesting.CompareValues(c.ExpectResult, result, opts...); err != nil { + t.Errorf("expect c.ExpectResult value match:\n%v", err) + } + }) + } +} diff --git a/internal/protocoltest/jsonrpc10/deserializers.go b/internal/protocoltest/jsonrpc10/deserializers.go index 2632c69dece..6d3a7077f26 100644 --- a/internal/protocoltest/jsonrpc10/deserializers.go +++ b/internal/protocoltest/jsonrpc10/deserializers.go @@ -9,6 +9,8 @@ import ( "encoding/json" "fmt" "github.com/aws/aws-sdk-go-v2/aws/protocol/restjson" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/document" + internaldocument "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/internal/document" "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/types" smithy "github.com/aws/smithy-go" smithyio "github.com/aws/smithy-go/io" @@ -808,14 +810,14 @@ func awsAwsjson10_deserializeOpErrorNoInputAndOutput(response *smithyhttp.Respon } } -type awsAwsjson10_deserializeOpPutWithContentEncoding struct { +type awsAwsjson10_deserializeOpOperationWithDefaults struct { } -func (*awsAwsjson10_deserializeOpPutWithContentEncoding) ID() string { +func (*awsAwsjson10_deserializeOpOperationWithDefaults) ID() string { return "OperationDeserializer" } -func (m *awsAwsjson10_deserializeOpPutWithContentEncoding) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( +func (m *awsAwsjson10_deserializeOpOperationWithDefaults) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( out middleware.DeserializeOutput, metadata middleware.Metadata, err error, ) { out, metadata, err = next.HandleDeserialize(ctx, in) @@ -829,21 +831,43 @@ func (m *awsAwsjson10_deserializeOpPutWithContentEncoding) HandleDeserialize(ctx } if response.StatusCode < 200 || response.StatusCode >= 300 { - return out, metadata, awsAwsjson10_deserializeOpErrorPutWithContentEncoding(response, &metadata) + return out, metadata, awsAwsjson10_deserializeOpErrorOperationWithDefaults(response, &metadata) } - output := &PutWithContentEncodingOutput{} + output := &OperationWithDefaultsOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { - return out, metadata, &smithy.DeserializationError{ - Err: fmt.Errorf("failed to discard response body, %w", err), + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(response.Body, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return out, metadata, err + } + + err = awsAwsjson10_deserializeOpDocumentOperationWithDefaultsOutput(&output, shape) + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), } + return out, metadata, err } return out, metadata, err } -func awsAwsjson10_deserializeOpErrorPutWithContentEncoding(response *smithyhttp.Response, metadata *middleware.Metadata) error { +func awsAwsjson10_deserializeOpErrorOperationWithDefaults(response *smithyhttp.Response, metadata *middleware.Metadata) error { var errorBuffer bytes.Buffer if _, err := io.Copy(&errorBuffer, response.Body); err != nil { return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} @@ -894,14 +918,14 @@ func awsAwsjson10_deserializeOpErrorPutWithContentEncoding(response *smithyhttp. } } -type awsAwsjson10_deserializeOpSimpleScalarProperties struct { +type awsAwsjson10_deserializeOpOperationWithNestedStructure struct { } -func (*awsAwsjson10_deserializeOpSimpleScalarProperties) ID() string { +func (*awsAwsjson10_deserializeOpOperationWithNestedStructure) ID() string { return "OperationDeserializer" } -func (m *awsAwsjson10_deserializeOpSimpleScalarProperties) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( +func (m *awsAwsjson10_deserializeOpOperationWithNestedStructure) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( out middleware.DeserializeOutput, metadata middleware.Metadata, err error, ) { out, metadata, err = next.HandleDeserialize(ctx, in) @@ -915,9 +939,9 @@ func (m *awsAwsjson10_deserializeOpSimpleScalarProperties) HandleDeserialize(ctx } if response.StatusCode < 200 || response.StatusCode >= 300 { - return out, metadata, awsAwsjson10_deserializeOpErrorSimpleScalarProperties(response, &metadata) + return out, metadata, awsAwsjson10_deserializeOpErrorOperationWithNestedStructure(response, &metadata) } - output := &SimpleScalarPropertiesOutput{} + output := &OperationWithNestedStructureOutput{} out.Result = output var buff [1024]byte @@ -937,7 +961,7 @@ func (m *awsAwsjson10_deserializeOpSimpleScalarProperties) HandleDeserialize(ctx return out, metadata, err } - err = awsAwsjson10_deserializeOpDocumentSimpleScalarPropertiesOutput(&output, shape) + err = awsAwsjson10_deserializeOpDocumentOperationWithNestedStructureOutput(&output, shape) if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) @@ -951,7 +975,7 @@ func (m *awsAwsjson10_deserializeOpSimpleScalarProperties) HandleDeserialize(ctx return out, metadata, err } -func awsAwsjson10_deserializeOpErrorSimpleScalarProperties(response *smithyhttp.Response, metadata *middleware.Metadata) error { +func awsAwsjson10_deserializeOpErrorOperationWithNestedStructure(response *smithyhttp.Response, metadata *middleware.Metadata) error { var errorBuffer bytes.Buffer if _, err := io.Copy(&errorBuffer, response.Body); err != nil { return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} @@ -1002,11 +1026,36 @@ func awsAwsjson10_deserializeOpErrorSimpleScalarProperties(response *smithyhttp. } } -func awsAwsjson10_deserializeErrorComplexError(response *smithyhttp.Response, errorBody *bytes.Reader) error { +type awsAwsjson10_deserializeOpOperationWithRequiredMembers struct { +} + +func (*awsAwsjson10_deserializeOpOperationWithRequiredMembers) ID() string { + return "OperationDeserializer" +} + +func (m *awsAwsjson10_deserializeOpOperationWithRequiredMembers) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsAwsjson10_deserializeOpErrorOperationWithRequiredMembers(response, &metadata) + } + output := &OperationWithRequiredMembersOutput{} + out.Result = output + var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(response.Body, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -1017,12 +1066,10 @@ func awsAwsjson10_deserializeErrorComplexError(response *smithyhttp.Response, er Err: fmt.Errorf("failed to decode response body, %w", err), Snapshot: snapshot.Bytes(), } - return err + return out, metadata, err } - output := &types.ComplexError{} - err := awsAwsjson10_deserializeDocumentComplexError(&output, shape) - + err = awsAwsjson10_deserializeOpDocumentOperationWithRequiredMembersOutput(&output, shape) if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) @@ -1030,22 +1077,35 @@ func awsAwsjson10_deserializeErrorComplexError(response *smithyhttp.Response, er Err: fmt.Errorf("failed to decode response body, %w", err), Snapshot: snapshot.Bytes(), } - return err + return out, metadata, err } - errorBody.Seek(0, io.SeekStart) - return output + return out, metadata, err } -func awsAwsjson10_deserializeErrorFooError(response *smithyhttp.Response, errorBody *bytes.Reader) error { +func awsAwsjson10_deserializeOpErrorOperationWithRequiredMembers(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + headerCode := response.Header.Get("X-Amzn-ErrorType") + if len(headerCode) != 0 { + errorCode = restjson.SanitizeErrorCode(headerCode) + } + var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) body := io.TeeReader(errorBody, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() - var shape interface{} - if err := decoder.Decode(&shape); err != nil && err != io.EOF { + jsonCode, message, err := restjson.GetErrorInfo(decoder) + if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) err = &smithy.DeserializationError{ @@ -1055,9 +1115,82 @@ func awsAwsjson10_deserializeErrorFooError(response *smithyhttp.Response, errorB return err } - output := &types.FooError{} - err := awsAwsjson10_deserializeDocumentFooError(&output, shape) + errorBody.Seek(0, io.SeekStart) + if len(headerCode) == 0 && len(jsonCode) != 0 { + errorCode = restjson.SanitizeErrorCode(jsonCode) + } + if len(message) != 0 { + errorMessage = message + } + + switch { + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } +} + +type awsAwsjson10_deserializeOpPutWithContentEncoding struct { +} + +func (*awsAwsjson10_deserializeOpPutWithContentEncoding) ID() string { + return "OperationDeserializer" +} + +func (m *awsAwsjson10_deserializeOpPutWithContentEncoding) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsAwsjson10_deserializeOpErrorPutWithContentEncoding(response, &metadata) + } + output := &PutWithContentEncodingOutput{} + out.Result = output + + if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + return out, metadata, &smithy.DeserializationError{ + Err: fmt.Errorf("failed to discard response body, %w", err), + } + } + + return out, metadata, err +} + +func awsAwsjson10_deserializeOpErrorPutWithContentEncoding(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + headerCode := response.Header.Get("X-Amzn-ErrorType") + if len(headerCode) != 0 { + errorCode = restjson.SanitizeErrorCode(headerCode) + } + + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + jsonCode, message, err := restjson.GetErrorInfo(decoder) if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) @@ -1069,14 +1202,54 @@ func awsAwsjson10_deserializeErrorFooError(response *smithyhttp.Response, errorB } errorBody.Seek(0, io.SeekStart) - return output + if len(headerCode) == 0 && len(jsonCode) != 0 { + errorCode = restjson.SanitizeErrorCode(jsonCode) + } + if len(message) != 0 { + errorMessage = message + } + + switch { + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } } -func awsAwsjson10_deserializeErrorInvalidGreeting(response *smithyhttp.Response, errorBody *bytes.Reader) error { +type awsAwsjson10_deserializeOpSimpleScalarProperties struct { +} + +func (*awsAwsjson10_deserializeOpSimpleScalarProperties) ID() string { + return "OperationDeserializer" +} + +func (m *awsAwsjson10_deserializeOpSimpleScalarProperties) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsAwsjson10_deserializeOpErrorSimpleScalarProperties(response, &metadata) + } + output := &SimpleScalarPropertiesOutput{} + out.Result = output + var buff [1024]byte ringBuffer := smithyio.NewRingBuffer(buff[:]) - body := io.TeeReader(errorBody, ringBuffer) + body := io.TeeReader(response.Body, ringBuffer) decoder := json.NewDecoder(body) decoder.UseNumber() var shape interface{} @@ -1087,12 +1260,10 @@ func awsAwsjson10_deserializeErrorInvalidGreeting(response *smithyhttp.Response, Err: fmt.Errorf("failed to decode response body, %w", err), Snapshot: snapshot.Bytes(), } - return err + return out, metadata, err } - output := &types.InvalidGreeting{} - err := awsAwsjson10_deserializeDocumentInvalidGreeting(&output, shape) - + err = awsAwsjson10_deserializeOpDocumentSimpleScalarPropertiesOutput(&output, shape) if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) @@ -1100,37 +1271,192 @@ func awsAwsjson10_deserializeErrorInvalidGreeting(response *smithyhttp.Response, Err: fmt.Errorf("failed to decode response body, %w", err), Snapshot: snapshot.Bytes(), } - return err + return out, metadata, err } - errorBody.Seek(0, io.SeekStart) - return output + return out, metadata, err } -func awsAwsjson10_deserializeDocumentComplexError(v **types.ComplexError, value interface{}) error { - if v == nil { - return fmt.Errorf("unexpected nil of type %T", v) - } - if value == nil { - return nil +func awsAwsjson10_deserializeOpErrorSimpleScalarProperties(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} } + errorBody := bytes.NewReader(errorBuffer.Bytes()) - shape, ok := value.(map[string]interface{}) - if !ok { - return fmt.Errorf("unexpected JSON type %v", value) - } + errorCode := "UnknownError" + errorMessage := errorCode - var sv *types.ComplexError - if *v == nil { - sv = &types.ComplexError{} - } else { - sv = *v + headerCode := response.Header.Get("X-Amzn-ErrorType") + if len(headerCode) != 0 { + errorCode = restjson.SanitizeErrorCode(headerCode) } - for key, value := range shape { - switch key { - case "Nested": - if err := awsAwsjson10_deserializeDocumentComplexNestedErrorData(&sv.Nested, value); err != nil { + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + jsonCode, message, err := restjson.GetErrorInfo(decoder) + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + if len(headerCode) == 0 && len(jsonCode) != 0 { + errorCode = restjson.SanitizeErrorCode(jsonCode) + } + if len(message) != 0 { + errorMessage = message + } + + switch { + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } +} + +func awsAwsjson10_deserializeErrorComplexError(response *smithyhttp.Response, errorBody *bytes.Reader) error { + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + output := &types.ComplexError{} + err := awsAwsjson10_deserializeDocumentComplexError(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + return output +} + +func awsAwsjson10_deserializeErrorFooError(response *smithyhttp.Response, errorBody *bytes.Reader) error { + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + output := &types.FooError{} + err := awsAwsjson10_deserializeDocumentFooError(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + return output +} + +func awsAwsjson10_deserializeErrorInvalidGreeting(response *smithyhttp.Response, errorBody *bytes.Reader) error { + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + output := &types.InvalidGreeting{} + err := awsAwsjson10_deserializeDocumentInvalidGreeting(&output, shape) + + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + return output +} + +func awsAwsjson10_deserializeDocumentComplexError(v **types.ComplexError, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.ComplexError + if *v == nil { + sv = &types.ComplexError{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "Nested": + if err := awsAwsjson10_deserializeDocumentComplexNestedErrorData(&sv.Nested, value); err != nil { return err } @@ -1192,7 +1518,7 @@ func awsAwsjson10_deserializeDocumentComplexNestedErrorData(v **types.ComplexNes return nil } -func awsAwsjson10_deserializeDocumentFooError(v **types.FooError, value interface{}) error { +func awsAwsjson10_deserializeDocumentDialog(v **types.Dialog, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) } @@ -1205,15 +1531,38 @@ func awsAwsjson10_deserializeDocumentFooError(v **types.FooError, value interfac return fmt.Errorf("unexpected JSON type %v", value) } - var sv *types.FooError + var sv *types.Dialog if *v == nil { - sv = &types.FooError{} + sv = &types.Dialog{} } else { sv = *v } for key, value := range shape { switch key { + case "farewell": + if err := awsAwsjson10_deserializeDocumentFarewell(&sv.Farewell, value); err != nil { + return err + } + + case "greeting": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Greeting = ptr.String(jtv) + } + + case "language": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Language = ptr.String(jtv) + } + default: _, _ = key, value @@ -1223,7 +1572,41 @@ func awsAwsjson10_deserializeDocumentFooError(v **types.FooError, value interfac return nil } -func awsAwsjson10_deserializeDocumentInvalidGreeting(v **types.InvalidGreeting, value interface{}) error { +func awsAwsjson10_deserializeDocumentDialogList(v *[]types.Dialog, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.([]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var cv []types.Dialog + if *v == nil { + cv = []types.Dialog{} + } else { + cv = *v + } + + for _, value := range shape { + var col types.Dialog + destAddr := &col + if err := awsAwsjson10_deserializeDocumentDialog(&destAddr, value); err != nil { + return err + } + col = *destAddr + cv = append(cv, col) + + } + *v = cv + return nil +} + +func awsAwsjson10_deserializeDocumentDialogMap(v *map[string]types.Dialog, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) } @@ -1236,22 +1619,57 @@ func awsAwsjson10_deserializeDocumentInvalidGreeting(v **types.InvalidGreeting, return fmt.Errorf("unexpected JSON type %v", value) } - var sv *types.InvalidGreeting + var mv map[string]types.Dialog if *v == nil { - sv = &types.InvalidGreeting{} + mv = map[string]types.Dialog{} + } else { + mv = *v + } + + for key, value := range shape { + var parsedVal types.Dialog + mapVar := parsedVal + destAddr := &mapVar + if err := awsAwsjson10_deserializeDocumentDialog(&destAddr, value); err != nil { + return err + } + parsedVal = *destAddr + mv[key] = parsedVal + + } + *v = mv + return nil +} + +func awsAwsjson10_deserializeDocumentFarewell(v **types.Farewell, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.Farewell + if *v == nil { + sv = &types.Farewell{} } else { sv = *v } for key, value := range shape { switch key { - case "Message": + case "phrase": if value != nil { jtv, ok := value.(string) if !ok { return fmt.Errorf("expected String to be of type string, got %T instead", value) } - sv.Message = ptr.String(jtv) + sv.Phrase = ptr.String(jtv) } default: @@ -1263,7 +1681,7 @@ func awsAwsjson10_deserializeDocumentInvalidGreeting(v **types.InvalidGreeting, return nil } -func awsAwsjson10_deserializeDocumentMyUnion(v *types.MyUnion, value interface{}) error { +func awsAwsjson10_deserializeDocumentFooError(v **types.FooError, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) } @@ -1276,10 +1694,81 @@ func awsAwsjson10_deserializeDocumentMyUnion(v *types.MyUnion, value interface{} return fmt.Errorf("unexpected JSON type %v", value) } - var uv types.MyUnion -loop: + var sv *types.FooError + if *v == nil { + sv = &types.FooError{} + } else { + sv = *v + } + for key, value := range shape { - if value == nil { + switch key { + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + +func awsAwsjson10_deserializeDocumentInvalidGreeting(v **types.InvalidGreeting, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *types.InvalidGreeting + if *v == nil { + sv = &types.InvalidGreeting{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "Message": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Message = ptr.String(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + +func awsAwsjson10_deserializeDocumentMyUnion(v *types.MyUnion, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var uv types.MyUnion +loop: + for key, value := range shape { + if value == nil { continue } switch key { @@ -1422,6 +1911,150 @@ loop: return nil } +func awsAwsjson10_deserializeDocumentRequiredStringList(v *[]string, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.([]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var cv []string + if *v == nil { + cv = []string{} + } else { + cv = *v + } + + for _, value := range shape { + var col string + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + col = jtv + } + cv = append(cv, col) + + } + *v = cv + return nil +} + +func awsAwsjson10_deserializeDocumentRequiredStringMap(v *map[string]string, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var mv map[string]string + if *v == nil { + mv = map[string]string{} + } else { + mv = *v + } + + for key, value := range shape { + var parsedVal string + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + parsedVal = jtv + } + mv[key] = parsedVal + + } + *v = mv + return nil +} + +func awsAwsjson10_deserializeDocumentTestStringList(v *[]string, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.([]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var cv []string + if *v == nil { + cv = []string{} + } else { + cv = *v + } + + for _, value := range shape { + var col string + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + col = jtv + } + cv = append(cv, col) + + } + *v = cv + return nil +} + +func awsAwsjson10_deserializeDocumentTestStringMap(v *map[string]string, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var mv map[string]string + if *v == nil { + mv = map[string]string{} + } else { + mv = *v + } + + for key, value := range shape { + var parsedVal string + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + parsedVal = jtv + } + mv[key] = parsedVal + + } + *v = mv + return nil +} + func awsAwsjson10_deserializeDocumentGreetingStruct(v **types.GreetingStruct, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) @@ -1534,6 +2167,14 @@ func awsAwsjson10_deserializeDocumentStringMap(v *map[string]string, value inter return nil } +func awsAwsjson10_deserializeDocumentDocument(v *document.Interface, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + *v = internaldocument.NewDocumentUnmarshaler(value) + return nil +} + func awsAwsjson10_deserializeOpDocumentEmptyInputAndEmptyOutputOutput(v **EmptyInputAndEmptyOutputOutput, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) @@ -1672,6 +2313,515 @@ func awsAwsjson10_deserializeOpDocumentNoInputAndOutputOutput(v **NoInputAndOutp return nil } +func awsAwsjson10_deserializeOpDocumentOperationWithDefaultsOutput(v **OperationWithDefaultsOutput, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *OperationWithDefaultsOutput + if *v == nil { + sv = &OperationWithDefaultsOutput{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "defaultBlob": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected Blob to be []byte, got %T instead", value) + } + dv, err := base64.StdEncoding.DecodeString(jtv) + if err != nil { + return fmt.Errorf("failed to base64 decode Blob, %w", err) + } + sv.DefaultBlob = dv + } + + case "defaultBoolean": + if value != nil { + jtv, ok := value.(bool) + if !ok { + return fmt.Errorf("expected Boolean to be of type *bool, got %T instead", value) + } + sv.DefaultBoolean = ptr.Bool(jtv) + } + + case "defaultByte": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Byte to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.DefaultByte = ptr.Int8(int8(i64)) + } + + case "defaultDocumentBoolean": + if err := awsAwsjson10_deserializeDocumentDocument(&sv.DefaultDocumentBoolean, value); err != nil { + return err + } + + case "defaultDocumentList": + if err := awsAwsjson10_deserializeDocumentDocument(&sv.DefaultDocumentList, value); err != nil { + return err + } + + case "defaultDocumentMap": + if err := awsAwsjson10_deserializeDocumentDocument(&sv.DefaultDocumentMap, value); err != nil { + return err + } + + case "defaultDocumentString": + if err := awsAwsjson10_deserializeDocumentDocument(&sv.DefaultDocumentString, value); err != nil { + return err + } + + case "defaultDouble": + if value != nil { + switch jtv := value.(type) { + case json.Number: + f64, err := jtv.Float64() + if err != nil { + return err + } + sv.DefaultDouble = ptr.Float64(f64) + + case string: + var f64 float64 + switch { + case strings.EqualFold(jtv, "NaN"): + f64 = math.NaN() + + case strings.EqualFold(jtv, "Infinity"): + f64 = math.Inf(1) + + case strings.EqualFold(jtv, "-Infinity"): + f64 = math.Inf(-1) + + default: + return fmt.Errorf("unknown JSON number value: %s", jtv) + + } + sv.DefaultDouble = ptr.Float64(f64) + + default: + return fmt.Errorf("expected Double to be a JSON Number, got %T instead", value) + + } + } + + case "defaultEnum": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected TestEnum to be of type string, got %T instead", value) + } + sv.DefaultEnum = types.TestEnum(jtv) + } + + case "defaultFloat": + if value != nil { + switch jtv := value.(type) { + case json.Number: + f64, err := jtv.Float64() + if err != nil { + return err + } + sv.DefaultFloat = ptr.Float32(float32(f64)) + + case string: + var f64 float64 + switch { + case strings.EqualFold(jtv, "NaN"): + f64 = math.NaN() + + case strings.EqualFold(jtv, "Infinity"): + f64 = math.Inf(1) + + case strings.EqualFold(jtv, "-Infinity"): + f64 = math.Inf(-1) + + default: + return fmt.Errorf("unknown JSON number value: %s", jtv) + + } + sv.DefaultFloat = ptr.Float32(float32(f64)) + + default: + return fmt.Errorf("expected Float to be a JSON Number, got %T instead", value) + + } + } + + case "defaultInteger": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Integer to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.DefaultInteger = ptr.Int32(int32(i64)) + } + + case "defaultIntEnum": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected TestIntEnum to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.DefaultIntEnum = int32(i64) + } + + case "defaultList": + if err := awsAwsjson10_deserializeDocumentTestStringList(&sv.DefaultList, value); err != nil { + return err + } + + case "defaultLong": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Long to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.DefaultLong = ptr.Int64(i64) + } + + case "defaultMap": + if err := awsAwsjson10_deserializeDocumentTestStringMap(&sv.DefaultMap, value); err != nil { + return err + } + + case "defaultNullDocument": + if err := awsAwsjson10_deserializeDocumentDocument(&sv.DefaultNullDocument, value); err != nil { + return err + } + + case "defaultShort": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Short to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.DefaultShort = ptr.Int16(int16(i64)) + } + + case "defaultString": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.DefaultString = ptr.String(jtv) + } + + case "defaultTimestamp": + if value != nil { + switch jtv := value.(type) { + case json.Number: + f64, err := jtv.Float64() + if err != nil { + return err + } + sv.DefaultTimestamp = ptr.Time(smithytime.ParseEpochSeconds(f64)) + + default: + return fmt.Errorf("expected Timestamp to be a JSON Number, got %T instead", value) + + } + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + +func awsAwsjson10_deserializeOpDocumentOperationWithNestedStructureOutput(v **OperationWithNestedStructureOutput, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *OperationWithNestedStructureOutput + if *v == nil { + sv = &OperationWithNestedStructureOutput{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "dialog": + if err := awsAwsjson10_deserializeDocumentDialog(&sv.Dialog, value); err != nil { + return err + } + + case "dialogList": + if err := awsAwsjson10_deserializeDocumentDialogList(&sv.DialogList, value); err != nil { + return err + } + + case "dialogMap": + if err := awsAwsjson10_deserializeDocumentDialogMap(&sv.DialogMap, value); err != nil { + return err + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + +func awsAwsjson10_deserializeOpDocumentOperationWithRequiredMembersOutput(v **OperationWithRequiredMembersOutput, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *OperationWithRequiredMembersOutput + if *v == nil { + sv = &OperationWithRequiredMembersOutput{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "requiredBlob": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected Blob to be []byte, got %T instead", value) + } + dv, err := base64.StdEncoding.DecodeString(jtv) + if err != nil { + return fmt.Errorf("failed to base64 decode Blob, %w", err) + } + sv.RequiredBlob = dv + } + + case "requiredBoolean": + if value != nil { + jtv, ok := value.(bool) + if !ok { + return fmt.Errorf("expected Boolean to be of type *bool, got %T instead", value) + } + sv.RequiredBoolean = ptr.Bool(jtv) + } + + case "requiredByte": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Byte to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.RequiredByte = ptr.Int8(int8(i64)) + } + + case "requiredDouble": + if value != nil { + switch jtv := value.(type) { + case json.Number: + f64, err := jtv.Float64() + if err != nil { + return err + } + sv.RequiredDouble = ptr.Float64(f64) + + case string: + var f64 float64 + switch { + case strings.EqualFold(jtv, "NaN"): + f64 = math.NaN() + + case strings.EqualFold(jtv, "Infinity"): + f64 = math.Inf(1) + + case strings.EqualFold(jtv, "-Infinity"): + f64 = math.Inf(-1) + + default: + return fmt.Errorf("unknown JSON number value: %s", jtv) + + } + sv.RequiredDouble = ptr.Float64(f64) + + default: + return fmt.Errorf("expected Double to be a JSON Number, got %T instead", value) + + } + } + + case "requiredFloat": + if value != nil { + switch jtv := value.(type) { + case json.Number: + f64, err := jtv.Float64() + if err != nil { + return err + } + sv.RequiredFloat = ptr.Float32(float32(f64)) + + case string: + var f64 float64 + switch { + case strings.EqualFold(jtv, "NaN"): + f64 = math.NaN() + + case strings.EqualFold(jtv, "Infinity"): + f64 = math.Inf(1) + + case strings.EqualFold(jtv, "-Infinity"): + f64 = math.Inf(-1) + + default: + return fmt.Errorf("unknown JSON number value: %s", jtv) + + } + sv.RequiredFloat = ptr.Float32(float32(f64)) + + default: + return fmt.Errorf("expected Float to be a JSON Number, got %T instead", value) + + } + } + + case "requiredInteger": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Integer to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.RequiredInteger = ptr.Int32(int32(i64)) + } + + case "requiredList": + if err := awsAwsjson10_deserializeDocumentRequiredStringList(&sv.RequiredList, value); err != nil { + return err + } + + case "requiredLong": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Long to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.RequiredLong = ptr.Int64(i64) + } + + case "requiredMap": + if err := awsAwsjson10_deserializeDocumentRequiredStringMap(&sv.RequiredMap, value); err != nil { + return err + } + + case "requiredShort": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Short to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.RequiredShort = ptr.Int16(int16(i64)) + } + + case "requiredString": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.RequiredString = ptr.String(jtv) + } + + case "requiredTimestamp": + if value != nil { + switch jtv := value.(type) { + case json.Number: + f64, err := jtv.Float64() + if err != nil { + return err + } + sv.RequiredTimestamp = ptr.Time(smithytime.ParseEpochSeconds(f64)) + + default: + return fmt.Errorf("expected Timestamp to be a JSON Number, got %T instead", value) + + } + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + func awsAwsjson10_deserializeOpDocumentSimpleScalarPropertiesOutput(v **SimpleScalarPropertiesOutput, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) diff --git a/internal/protocoltest/jsonrpc10/document/doc.go b/internal/protocoltest/jsonrpc10/document/doc.go new file mode 100644 index 00000000000..2b06b14f3cd --- /dev/null +++ b/internal/protocoltest/jsonrpc10/document/doc.go @@ -0,0 +1,66 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +// Package document implements encoding and decoding of open-content that has a JSON-like data model. +// This data-model allows for UTF-8 strings, arbitrary precision numbers, booleans, nulls, a list of these values, and a +// map of UTF-8 strings to these values. +// +// Interface defines the semantics for how a document type is marshalled and unmarshalled for requests and responses +// for the service. To send a document as input to the service you use NewLazyDocument and pass it the Go type to be +// sent to the service. NewLazyDocument returns a document Interface type that encodes the provided Go type during +// the request serialization step after you have invoked an API client operation that uses the document type. +// +// The following examples show how you can create document types using basic Go types. +// +// NewLazyDocument(map[string]interface{}{ +// "favoriteNumber": 42, +// "fruits": []string{"apple", "orange"}, +// "capitals": map[string]interface{}{ +// "Washington": "Olympia", +// "Oregon": "Salem", +// }, +// "skyIsBlue": true, +// }) +// +// NewLazyDocument(3.14159) +// +// NewLazyDocument([]interface{"One", 2, 3, 3.5, "four"}) +// +// NewLazyDocument(true) +// +// Services can send document types as part of their API responses. To retrieve the content of a response document +// you use the UnmarshalSmithyDocument method on the response document. When calling UnmarshalSmithyDocument you pass +// a reference to the Go type that you want to unmarshal and map the response to. +// +// For example, if you expect to receive key/value map from the service response: +// +// var kv map[string]interface{} +// if err := outputDocument.UnmarshalSmithyDocument(&kv); err != nil { +// // handle error +// } +// +// If a service can return one or more data-types in the response, you can use an empty interface and type switch to +// dynamically handle the response type. +// +// var v interface{} +// if err := outputDocument.UnmarshalSmithyDocument(&v); err != nil { +// // handle error +// } +// +// switch vv := v.(type) { +// case map[string]interface{}: +// // handle key/value map +// case []interface{}: +// // handle array of values +// case bool: +// // handle boolean +// case document.Number: +// // handle an arbitrary precision number +// case string: +// // handle string +// default: +// // handle unknown case +// } +// +// The mapping of Go types to document types is covered in more depth in https://pkg.go.dev/github.com/aws/smithy-go/document +// including more in depth examples that cover user-defined structure types. +package document diff --git a/internal/protocoltest/jsonrpc10/document/document.go b/internal/protocoltest/jsonrpc10/document/document.go new file mode 100644 index 00000000000..11e83e9a73f --- /dev/null +++ b/internal/protocoltest/jsonrpc10/document/document.go @@ -0,0 +1,34 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package document + +import ( + internaldocument "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/internal/document" +) + +// Interface defines a document which is a protocol-agnostic type which supports a +// JSON-like data-model. You can use this type to send UTF-8 strings, arbitrary +// precision numbers, booleans, nulls, a list of these values, and a map of UTF-8 +// strings to these values. +// +// You create a document type using the NewLazyDocument function and passing it +// the Go type to marshal. When receiving a document in an API response, you use +// the document's UnmarshalSmithyDocument function to decode the response to your +// desired Go type. Unless documented specifically generated structure types in +// client packages or client types packages are not supported at this time. Such +// types embed a noSmithyDocumentSerde and will cause an error to be returned when +// attempting to send an API request. +// +// For more information see the accompanying package documentation and linked +// references. +type Interface = internaldocument.Interface + +// You create document type using the NewLazyDocument function and passing it the +// Go type to be marshaled and sent to the service. The document marshaler supports +// semantics similar to the encoding/json Go standard library. +// +// For more information see the accompanying package documentation and linked +// references. +func NewLazyDocument(v interface{}) Interface { + return internaldocument.NewDocumentMarshaler(v) +} diff --git a/internal/protocoltest/jsonrpc10/generated.json b/internal/protocoltest/jsonrpc10/generated.json index cb2bcc7902a..3fb24ea7e73 100644 --- a/internal/protocoltest/jsonrpc10/generated.json +++ b/internal/protocoltest/jsonrpc10/generated.json @@ -25,6 +25,12 @@ "api_op_NoInputAndNoOutput_test.go", "api_op_NoInputAndOutput.go", "api_op_NoInputAndOutput_test.go", + "api_op_OperationWithDefaults.go", + "api_op_OperationWithDefaults_test.go", + "api_op_OperationWithNestedStructure.go", + "api_op_OperationWithNestedStructure_test.go", + "api_op_OperationWithRequiredMembers.go", + "api_op_OperationWithRequiredMembers_test.go", "api_op_PutWithContentEncoding.go", "api_op_PutWithContentEncoding_test.go", "api_op_SimpleScalarProperties.go", @@ -32,10 +38,14 @@ "auth.go", "deserializers.go", "doc.go", + "document/doc.go", + "document/document.go", "endpoints.go", "endpoints_config_test.go", "endpoints_test.go", "generated.json", + "internal/document/document.go", + "internal/document/document_test.go", "internal/endpoints/endpoints.go", "internal/endpoints/endpoints_test.go", "options.go", diff --git a/internal/protocoltest/jsonrpc10/internal/document/document.go b/internal/protocoltest/jsonrpc10/internal/document/document.go new file mode 100644 index 00000000000..256b569b60f --- /dev/null +++ b/internal/protocoltest/jsonrpc10/internal/document/document.go @@ -0,0 +1,99 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package document + +import ( + "bytes" + "encoding/json" + smithydocument "github.com/aws/smithy-go/document" + smithydocumentjson "github.com/aws/smithy-go/document/json" +) + +// github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/internal/document.smithyDocument +// is an interface which is used to bind a document type to its service client. +type smithyDocument interface { + isSmithyDocument() +} + +// github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/internal/document.Interface +// is a JSON-like data model type that is protocol agnostic and is usedto send +// open-content to a service. +type Interface interface { + smithyDocument + smithydocument.Marshaler + smithydocument.Unmarshaler +} + +type documentMarshaler struct { + value interface{} +} + +func (m *documentMarshaler) UnmarshalSmithyDocument(v interface{}) error { + mBytes, err := m.MarshalSmithyDocument() + if err != nil { + return err + } + + jDecoder := json.NewDecoder(bytes.NewReader(mBytes)) + jDecoder.UseNumber() + + var jv interface{} + if err := jDecoder.Decode(&v); err != nil { + return err + } + + return NewDocumentUnmarshaler(v).UnmarshalSmithyDocument(&jv) +} + +func (m *documentMarshaler) MarshalSmithyDocument() ([]byte, error) { + return smithydocumentjson.NewEncoder().Encode(m.value) +} + +func (m *documentMarshaler) isSmithyDocument() {} + +var _ Interface = (*documentMarshaler)(nil) + +type documentUnmarshaler struct { + value interface{} +} + +func (m *documentUnmarshaler) UnmarshalSmithyDocument(v interface{}) error { + decoder := smithydocumentjson.NewDecoder() + return decoder.DecodeJSONInterface(m.value, v) +} + +func (m *documentUnmarshaler) MarshalSmithyDocument() ([]byte, error) { + return json.Marshal(m.value) +} + +func (m *documentUnmarshaler) isSmithyDocument() {} + +var _ Interface = (*documentUnmarshaler)(nil) + +// NewDocumentMarshaler creates a new document marshaler for the given input type +func NewDocumentMarshaler(v interface{}) Interface { + return &documentMarshaler{ + value: v, + } +} + +// NewDocumentUnmarshaler creates a new document unmarshaler for the given service +// response +func NewDocumentUnmarshaler(v interface{}) Interface { + return &documentUnmarshaler{ + value: v, + } +} + +// github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/internal/document.IsInterface +// returns whether the given Interface implementation is a valid client +// implementation +func IsInterface(v Interface) (ok bool) { + defer func() { + if err := recover(); err != nil { + ok = false + } + }() + v.isSmithyDocument() + return true +} diff --git a/internal/protocoltest/jsonrpc10/internal/document/document_test.go b/internal/protocoltest/jsonrpc10/internal/document/document_test.go new file mode 100644 index 00000000000..775645dcd6e --- /dev/null +++ b/internal/protocoltest/jsonrpc10/internal/document/document_test.go @@ -0,0 +1,11 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package document + +import ( + smithydocument "github.com/aws/smithy-go/document" +) + +var _ smithyDocument = (Interface)(nil) +var _ smithydocument.Marshaler = (Interface)(nil) +var _ smithydocument.Unmarshaler = (Interface)(nil) diff --git a/internal/protocoltest/jsonrpc10/serializers.go b/internal/protocoltest/jsonrpc10/serializers.go index 64380aa2ad7..25aa270773c 100644 --- a/internal/protocoltest/jsonrpc10/serializers.go +++ b/internal/protocoltest/jsonrpc10/serializers.go @@ -6,6 +6,8 @@ import ( "bytes" "context" "fmt" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/document" + internaldocument "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/internal/document" "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/types" smithy "github.com/aws/smithy-go" "github.com/aws/smithy-go/encoding/httpbinding" @@ -438,6 +440,166 @@ func (m *awsAwsjson10_serializeOpNoInputAndOutput) HandleSerialize(ctx context.C return next.HandleSerialize(ctx, in) } +type awsAwsjson10_serializeOpOperationWithDefaults struct { +} + +func (*awsAwsjson10_serializeOpOperationWithDefaults) ID() string { + return "OperationSerializer" +} + +func (m *awsAwsjson10_serializeOpOperationWithDefaults) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*OperationWithDefaultsInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + operationPath := "/" + if len(request.Request.URL.Path) == 0 { + request.Request.URL.Path = operationPath + } else { + request.Request.URL.Path = path.Join(request.Request.URL.Path, operationPath) + if request.Request.URL.Path != "/" && operationPath[len(operationPath)-1] == '/' { + request.Request.URL.Path += "/" + } + } + request.Request.Method = "POST" + httpBindingEncoder, err := httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + httpBindingEncoder.SetHeader("Content-Type").String("application/x-amz-json-1.0") + httpBindingEncoder.SetHeader("X-Amz-Target").String("JsonRpc10.OperationWithDefaults") + + jsonEncoder := smithyjson.NewEncoder() + if err := awsAwsjson10_serializeOpDocumentOperationWithDefaultsInput(input, jsonEncoder.Value); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request, err = request.SetStream(bytes.NewReader(jsonEncoder.Bytes())); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request.Request, err = httpBindingEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + return next.HandleSerialize(ctx, in) +} + +type awsAwsjson10_serializeOpOperationWithNestedStructure struct { +} + +func (*awsAwsjson10_serializeOpOperationWithNestedStructure) ID() string { + return "OperationSerializer" +} + +func (m *awsAwsjson10_serializeOpOperationWithNestedStructure) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*OperationWithNestedStructureInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + operationPath := "/" + if len(request.Request.URL.Path) == 0 { + request.Request.URL.Path = operationPath + } else { + request.Request.URL.Path = path.Join(request.Request.URL.Path, operationPath) + if request.Request.URL.Path != "/" && operationPath[len(operationPath)-1] == '/' { + request.Request.URL.Path += "/" + } + } + request.Request.Method = "POST" + httpBindingEncoder, err := httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + httpBindingEncoder.SetHeader("Content-Type").String("application/x-amz-json-1.0") + httpBindingEncoder.SetHeader("X-Amz-Target").String("JsonRpc10.OperationWithNestedStructure") + + jsonEncoder := smithyjson.NewEncoder() + if err := awsAwsjson10_serializeOpDocumentOperationWithNestedStructureInput(input, jsonEncoder.Value); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request, err = request.SetStream(bytes.NewReader(jsonEncoder.Bytes())); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request.Request, err = httpBindingEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + return next.HandleSerialize(ctx, in) +} + +type awsAwsjson10_serializeOpOperationWithRequiredMembers struct { +} + +func (*awsAwsjson10_serializeOpOperationWithRequiredMembers) ID() string { + return "OperationSerializer" +} + +func (m *awsAwsjson10_serializeOpOperationWithRequiredMembers) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*OperationWithRequiredMembersInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + operationPath := "/" + if len(request.Request.URL.Path) == 0 { + request.Request.URL.Path = operationPath + } else { + request.Request.URL.Path = path.Join(request.Request.URL.Path, operationPath) + if request.Request.URL.Path != "/" && operationPath[len(operationPath)-1] == '/' { + request.Request.URL.Path += "/" + } + } + request.Request.Method = "POST" + httpBindingEncoder, err := httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + httpBindingEncoder.SetHeader("Content-Type").String("application/x-amz-json-1.0") + httpBindingEncoder.SetHeader("X-Amz-Target").String("JsonRpc10.OperationWithRequiredMembers") + + if request, err = request.SetStream(strings.NewReader(`{}`)); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request.Request, err = httpBindingEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + return next.HandleSerialize(ctx, in) +} + type awsAwsjson10_serializeOpPutWithContentEncoding struct { } @@ -547,6 +709,211 @@ func (m *awsAwsjson10_serializeOpSimpleScalarProperties) HandleSerialize(ctx con return next.HandleSerialize(ctx, in) } +func awsAwsjson10_serializeDocumentDefaults(v *types.Defaults, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.DefaultBlob != nil { + ok := object.Key("defaultBlob") + ok.Base64EncodeBytes(v.DefaultBlob) + } + + if v.DefaultBoolean != nil { + ok := object.Key("defaultBoolean") + ok.Boolean(*v.DefaultBoolean) + } + + if v.DefaultByte != nil { + ok := object.Key("defaultByte") + ok.Byte(*v.DefaultByte) + } + + if v.DefaultDocumentBoolean != nil { + ok := object.Key("defaultDocumentBoolean") + if err := awsAwsjson10_serializeDocumentDocument(v.DefaultDocumentBoolean, ok); err != nil { + return err + } + } + + if v.DefaultDocumentList != nil { + ok := object.Key("defaultDocumentList") + if err := awsAwsjson10_serializeDocumentDocument(v.DefaultDocumentList, ok); err != nil { + return err + } + } + + if v.DefaultDocumentMap != nil { + ok := object.Key("defaultDocumentMap") + if err := awsAwsjson10_serializeDocumentDocument(v.DefaultDocumentMap, ok); err != nil { + return err + } + } + + if v.DefaultDocumentString != nil { + ok := object.Key("defaultDocumentString") + if err := awsAwsjson10_serializeDocumentDocument(v.DefaultDocumentString, ok); err != nil { + return err + } + } + + if v.DefaultDouble != nil { + ok := object.Key("defaultDouble") + switch { + case math.IsNaN(*v.DefaultDouble): + ok.String("NaN") + + case math.IsInf(*v.DefaultDouble, 1): + ok.String("Infinity") + + case math.IsInf(*v.DefaultDouble, -1): + ok.String("-Infinity") + + default: + ok.Double(*v.DefaultDouble) + + } + } + + if len(v.DefaultEnum) > 0 { + ok := object.Key("defaultEnum") + ok.String(string(v.DefaultEnum)) + } + + if v.DefaultFloat != nil { + ok := object.Key("defaultFloat") + switch { + case math.IsNaN(float64(*v.DefaultFloat)): + ok.String("NaN") + + case math.IsInf(float64(*v.DefaultFloat), 1): + ok.String("Infinity") + + case math.IsInf(float64(*v.DefaultFloat), -1): + ok.String("-Infinity") + + default: + ok.Float(*v.DefaultFloat) + + } + } + + if v.DefaultInteger != nil { + ok := object.Key("defaultInteger") + ok.Integer(*v.DefaultInteger) + } + + if v.DefaultIntEnum != 0 { + ok := object.Key("defaultIntEnum") + ok.Integer(v.DefaultIntEnum) + } + + if v.DefaultList != nil { + ok := object.Key("defaultList") + if err := awsAwsjson10_serializeDocumentTestStringList(v.DefaultList, ok); err != nil { + return err + } + } + + if v.DefaultLong != nil { + ok := object.Key("defaultLong") + ok.Long(*v.DefaultLong) + } + + if v.DefaultMap != nil { + ok := object.Key("defaultMap") + if err := awsAwsjson10_serializeDocumentTestStringMap(v.DefaultMap, ok); err != nil { + return err + } + } + + if v.DefaultNullDocument != nil { + ok := object.Key("defaultNullDocument") + if err := awsAwsjson10_serializeDocumentDocument(v.DefaultNullDocument, ok); err != nil { + return err + } + } + + if v.DefaultShort != nil { + ok := object.Key("defaultShort") + ok.Short(*v.DefaultShort) + } + + if v.DefaultString != nil { + ok := object.Key("defaultString") + ok.String(*v.DefaultString) + } + + if v.DefaultTimestamp != nil { + ok := object.Key("defaultTimestamp") + ok.Double(smithytime.FormatEpochSeconds(*v.DefaultTimestamp)) + } + + return nil +} + +func awsAwsjson10_serializeDocumentDialog(v *types.Dialog, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.Farewell != nil { + ok := object.Key("farewell") + if err := awsAwsjson10_serializeDocumentFarewell(v.Farewell, ok); err != nil { + return err + } + } + + if v.Greeting != nil { + ok := object.Key("greeting") + ok.String(*v.Greeting) + } + + if v.Language != nil { + ok := object.Key("language") + ok.String(*v.Language) + } + + return nil +} + +func awsAwsjson10_serializeDocumentDialogList(v []types.Dialog, value smithyjson.Value) error { + array := value.Array() + defer array.Close() + + for i := range v { + av := array.Value() + if err := awsAwsjson10_serializeDocumentDialog(&v[i], av); err != nil { + return err + } + } + return nil +} + +func awsAwsjson10_serializeDocumentDialogMap(v map[string]types.Dialog, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + for key := range v { + om := object.Key(key) + mapVar := v[key] + if err := awsAwsjson10_serializeDocumentDialog(&mapVar, om); err != nil { + return err + } + } + return nil +} + +func awsAwsjson10_serializeDocumentFarewell(v *types.Farewell, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.Phrase != nil { + ok := object.Key("phrase") + ok.String(*v.Phrase) + } + + return nil +} + func awsAwsjson10_serializeDocumentMyUnion(v types.MyUnion, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -605,6 +972,56 @@ func awsAwsjson10_serializeDocumentMyUnion(v types.MyUnion, value smithyjson.Val return nil } +func awsAwsjson10_serializeDocumentTestStringList(v []string, value smithyjson.Value) error { + array := value.Array() + defer array.Close() + + for i := range v { + av := array.Value() + av.String(v[i]) + } + return nil +} + +func awsAwsjson10_serializeDocumentTestStringMap(v map[string]string, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + for key := range v { + om := object.Key(key) + om.String(v[key]) + } + return nil +} + +func awsAwsjson10_serializeDocumentTopLevel(v *types.TopLevel, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.Dialog != nil { + ok := object.Key("dialog") + if err := awsAwsjson10_serializeDocumentDialog(v.Dialog, ok); err != nil { + return err + } + } + + if v.DialogList != nil { + ok := object.Key("dialogList") + if err := awsAwsjson10_serializeDocumentDialogList(v.DialogList, ok); err != nil { + return err + } + } + + if v.DialogMap != nil { + ok := object.Key("dialogMap") + if err := awsAwsjson10_serializeDocumentDialogMap(v.DialogMap, ok); err != nil { + return err + } + } + + return nil +} + func awsAwsjson10_serializeDocumentGreetingStruct(v *types.GreetingStruct, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -639,6 +1056,21 @@ func awsAwsjson10_serializeDocumentStringMap(v map[string]string, value smithyjs return nil } +func awsAwsjson10_serializeDocumentDocument(v document.Interface, value smithyjson.Value) error { + if v == nil { + return nil + } + if !internaldocument.IsInterface(v) { + return fmt.Errorf("%T is not a compatible document type", v) + } + db, err := v.MarshalSmithyDocument() + if err != nil { + return err + } + value.Write(db) + return nil +} + func awsAwsjson10_serializeOpDocumentEmptyInputAndEmptyOutputInput(v *EmptyInputAndEmptyOutputInput, value smithyjson.Value) error { object := value.Object() defer object.Close() @@ -684,6 +1116,39 @@ func awsAwsjson10_serializeOpDocumentJsonUnionsInput(v *JsonUnionsInput, value s return nil } +func awsAwsjson10_serializeOpDocumentOperationWithDefaultsInput(v *OperationWithDefaultsInput, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.Defaults != nil { + ok := object.Key("defaults") + if err := awsAwsjson10_serializeDocumentDefaults(v.Defaults, ok); err != nil { + return err + } + } + + if v.TopLevelDefault != nil { + ok := object.Key("topLevelDefault") + ok.String(*v.TopLevelDefault) + } + + return nil +} + +func awsAwsjson10_serializeOpDocumentOperationWithNestedStructureInput(v *OperationWithNestedStructureInput, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.TopLevel != nil { + ok := object.Key("topLevel") + if err := awsAwsjson10_serializeDocumentTopLevel(v.TopLevel, ok); err != nil { + return err + } + } + + return nil +} + func awsAwsjson10_serializeOpDocumentPutWithContentEncodingInput(v *PutWithContentEncodingInput, value smithyjson.Value) error { object := value.Object() defer object.Close() diff --git a/internal/protocoltest/jsonrpc10/types/enums.go b/internal/protocoltest/jsonrpc10/types/enums.go index 6652e863c7a..14f15a9f2c3 100644 --- a/internal/protocoltest/jsonrpc10/types/enums.go +++ b/internal/protocoltest/jsonrpc10/types/enums.go @@ -2,6 +2,34 @@ package types +type TestEnum string + +// Enum values for TestEnum +const ( + TestEnumFoo TestEnum = "FOO" + TestEnumBar TestEnum = "BAR" + TestEnumBaz TestEnum = "BAZ" +) + +// Values returns all known values for TestEnum. Note that this can be expanded in +// the future, and so it is only as up to date as the client. The ordering of this +// slice is not guaranteed to be stable across updates. +func (TestEnum) Values() []TestEnum { + return []TestEnum{ + "FOO", + "BAR", + "BAZ", + } +} + +type TestIntEnum = int32 + +// Enum values for TestIntEnum +const ( + TestIntEnumOne TestIntEnum = 1 + TestIntEnumTwo TestIntEnum = 2 +) + type FooEnum string // Enum values for FooEnum diff --git a/internal/protocoltest/jsonrpc10/types/types.go b/internal/protocoltest/jsonrpc10/types/types.go index e3ec082823d..ba44f8f0416 100644 --- a/internal/protocoltest/jsonrpc10/types/types.go +++ b/internal/protocoltest/jsonrpc10/types/types.go @@ -3,6 +3,7 @@ package types import ( + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/document" smithydocument "github.com/aws/smithy-go/document" "time" ) @@ -13,6 +14,64 @@ type ComplexNestedErrorData struct { noSmithyDocumentSerde } +type Defaults struct { + DefaultBlob []byte + + DefaultBoolean *bool + + DefaultByte *int8 + + DefaultDocumentBoolean document.Interface + + DefaultDocumentList document.Interface + + DefaultDocumentMap document.Interface + + DefaultDocumentString document.Interface + + DefaultDouble *float64 + + DefaultEnum TestEnum + + DefaultFloat *float32 + + DefaultIntEnum TestIntEnum + + DefaultInteger *int32 + + DefaultList []string + + DefaultLong *int64 + + DefaultMap map[string]string + + DefaultNullDocument document.Interface + + DefaultShort *int16 + + DefaultString *string + + DefaultTimestamp *time.Time + + noSmithyDocumentSerde +} + +type Dialog struct { + Farewell *Farewell + + Greeting *string + + Language *string + + noSmithyDocumentSerde +} + +type Farewell struct { + Phrase *string + + noSmithyDocumentSerde +} + // A union with a representative set of types for members. // // The following types satisfy this interface: @@ -111,6 +170,18 @@ type MyUnionMemberTimestampValue struct { func (*MyUnionMemberTimestampValue) isMyUnion() {} +type TopLevel struct { + + // This member is required. + Dialog *Dialog + + DialogList []Dialog + + DialogMap map[string]Dialog + + noSmithyDocumentSerde +} + type GreetingStruct struct { Hi *string diff --git a/internal/protocoltest/jsonrpc10/validators.go b/internal/protocoltest/jsonrpc10/validators.go index c76ebbf67e7..a9d112c75d4 100644 --- a/internal/protocoltest/jsonrpc10/validators.go +++ b/internal/protocoltest/jsonrpc10/validators.go @@ -5,6 +5,7 @@ package jsonrpc10 import ( "context" "fmt" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/jsonrpc10/types" smithy "github.com/aws/smithy-go" "github.com/aws/smithy-go/middleware" ) @@ -29,10 +30,49 @@ func (m *validateOpEndpointWithHostLabelOperation) HandleInitialize(ctx context. return next.HandleInitialize(ctx, in) } +type validateOpOperationWithNestedStructure struct { +} + +func (*validateOpOperationWithNestedStructure) ID() string { + return "OperationInputValidation" +} + +func (m *validateOpOperationWithNestedStructure) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( + out middleware.InitializeOutput, metadata middleware.Metadata, err error, +) { + input, ok := in.Parameters.(*OperationWithNestedStructureInput) + if !ok { + return out, metadata, fmt.Errorf("unknown input parameters type %T", in.Parameters) + } + if err := validateOpOperationWithNestedStructureInput(input); err != nil { + return out, metadata, err + } + return next.HandleInitialize(ctx, in) +} + func addOpEndpointWithHostLabelOperationValidationMiddleware(stack *middleware.Stack) error { return stack.Initialize.Add(&validateOpEndpointWithHostLabelOperation{}, middleware.After) } +func addOpOperationWithNestedStructureValidationMiddleware(stack *middleware.Stack) error { + return stack.Initialize.Add(&validateOpOperationWithNestedStructure{}, middleware.After) +} + +func validateTopLevel(v *types.TopLevel) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "TopLevel"} + if v.Dialog == nil { + invalidParams.Add(smithy.NewErrParamRequired("Dialog")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + func validateOpEndpointWithHostLabelOperationInput(v *EndpointWithHostLabelOperationInput) error { if v == nil { return nil @@ -47,3 +87,22 @@ func validateOpEndpointWithHostLabelOperationInput(v *EndpointWithHostLabelOpera return nil } } + +func validateOpOperationWithNestedStructureInput(v *OperationWithNestedStructureInput) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "OperationWithNestedStructureInput"} + if v.TopLevel == nil { + invalidParams.Add(smithy.NewErrParamRequired("TopLevel")) + } else if v.TopLevel != nil { + if err := validateTopLevel(v.TopLevel); err != nil { + invalidParams.AddNested("TopLevel", err.(smithy.InvalidParamsError)) + } + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} diff --git a/internal/protocoltest/restxml/api_op_HttpEnumPayload.go b/internal/protocoltest/restxml/api_op_HttpEnumPayload.go new file mode 100644 index 00000000000..e13f9423df2 --- /dev/null +++ b/internal/protocoltest/restxml/api_op_HttpEnumPayload.go @@ -0,0 +1,123 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package restxml + +import ( + "context" + "fmt" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/restxml/types" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +func (c *Client) HttpEnumPayload(ctx context.Context, params *HttpEnumPayloadInput, optFns ...func(*Options)) (*HttpEnumPayloadOutput, error) { + if params == nil { + params = &HttpEnumPayloadInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "HttpEnumPayload", params, optFns, c.addOperationHttpEnumPayloadMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*HttpEnumPayloadOutput) + out.ResultMetadata = metadata + return out, nil +} + +type HttpEnumPayloadInput struct { + Payload types.StringEnum + + noSmithyDocumentSerde +} + +type HttpEnumPayloadOutput struct { + Payload types.StringEnum + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationHttpEnumPayloadMiddlewares(stack *middleware.Stack, options Options) (err error) { + if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { + return err + } + err = stack.Serialize.Add(&awsRestxml_serializeOpHttpEnumPayload{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsRestxml_deserializeOpHttpEnumPayload{}, middleware.After) + if err != nil { + return err + } + if err := addProtocolFinalizerMiddlewares(stack, options, "HttpEnumPayload"); err != nil { + return fmt.Errorf("add protocol finalizers: %v", err) + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addSetLoggerMiddleware(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addRetryMiddlewares(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { + return err + } + if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { + return err + } + if err = addClientUserAgent(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware_opHttpEnumPayload(options.Region), middleware.Before); err != nil { + return err + } + if err = awsmiddleware.AddRecursionDetection(stack); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + return nil +} + +func newServiceMetadataMiddleware_opHttpEnumPayload(region string) *awsmiddleware.RegisterServiceMetadata { + return &awsmiddleware.RegisterServiceMetadata{ + Region: region, + ServiceID: ServiceID, + OperationName: "HttpEnumPayload", + } +} diff --git a/internal/protocoltest/restxml/api_op_HttpEnumPayload_test.go b/internal/protocoltest/restxml/api_op_HttpEnumPayload_test.go new file mode 100644 index 00000000000..9cfbe42943c --- /dev/null +++ b/internal/protocoltest/restxml/api_op_HttpEnumPayload_test.go @@ -0,0 +1,202 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package restxml + +import ( + "bytes" + "context" + "github.com/aws/aws-sdk-go-v2/aws" + protocoltesthttp "github.com/aws/aws-sdk-go-v2/internal/protocoltest" + "github.com/aws/aws-sdk-go-v2/internal/protocoltest/restxml/types" + smithydocument "github.com/aws/smithy-go/document" + "github.com/aws/smithy-go/middleware" + smithyprivateprotocol "github.com/aws/smithy-go/private/protocol" + smithyrand "github.com/aws/smithy-go/rand" + smithytesting "github.com/aws/smithy-go/testing" + smithyhttp "github.com/aws/smithy-go/transport/http" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "io" + "io/ioutil" + "math" + "net/http" + "net/url" + "testing" +) + +func TestClient_HttpEnumPayload_awsRestxmlSerialize(t *testing.T) { + cases := map[string]struct { + Params *HttpEnumPayloadInput + ExpectMethod string + ExpectURIPath string + ExpectQuery []smithytesting.QueryItem + RequireQuery []string + ForbidQuery []string + ExpectHeader http.Header + RequireHeader []string + ForbidHeader []string + Host *url.URL + BodyMediaType string + BodyAssert func(io.Reader) error + }{ + "RestXmlEnumPayloadRequest": { + Params: &HttpEnumPayloadInput{ + Payload: types.StringEnum("enumvalue"), + }, + ExpectMethod: "POST", + ExpectURIPath: "/EnumPayload", + ExpectQuery: []smithytesting.QueryItem{}, + BodyAssert: func(actual io.Reader) error { + return smithytesting.CompareReaderBytes(actual, []byte(`enumvalue`)) + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + actualReq := &http.Request{} + serverURL := "http://localhost:8888/" + if c.Host != nil { + u, err := url.Parse(serverURL) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + u.Path = c.Host.Path + u.RawPath = c.Host.RawPath + u.RawQuery = c.Host.RawQuery + serverURL = u.String() + } + client := New(Options{ + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + HTTPClient: protocoltesthttp.NewClient(), + IdempotencyTokenProvider: smithyrand.NewUUIDIdempotencyToken(&smithytesting.ByteLoop{}), + Region: "us-west-2", + }) + result, err := client.HttpEnumPayload(context.Background(), c.Params, func(options *Options) { + options.APIOptions = append(options.APIOptions, func(stack *middleware.Stack) error { + return smithyprivateprotocol.AddCaptureRequestMiddleware(stack, actualReq) + }) + }) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + if e, a := c.ExpectMethod, actualReq.Method; e != a { + t.Errorf("expect %v method, got %v", e, a) + } + if e, a := c.ExpectURIPath, actualReq.URL.RawPath; e != a { + t.Errorf("expect %v path, got %v", e, a) + } + queryItems := smithytesting.ParseRawQuery(actualReq.URL.RawQuery) + smithytesting.AssertHasQuery(t, c.ExpectQuery, queryItems) + smithytesting.AssertHasQueryKeys(t, c.RequireQuery, queryItems) + smithytesting.AssertNotHaveQueryKeys(t, c.ForbidQuery, queryItems) + smithytesting.AssertHasHeader(t, c.ExpectHeader, actualReq.Header) + smithytesting.AssertHasHeaderKeys(t, c.RequireHeader, actualReq.Header) + smithytesting.AssertNotHaveHeaderKeys(t, c.ForbidHeader, actualReq.Header) + if c.BodyAssert != nil { + if err := c.BodyAssert(actualReq.Body); err != nil { + t.Errorf("expect body equal, got %v", err) + } + } + }) + } +} + +func TestClient_HttpEnumPayload_awsRestxmlDeserialize(t *testing.T) { + cases := map[string]struct { + StatusCode int + Header http.Header + BodyMediaType string + Body []byte + ExpectResult *HttpEnumPayloadOutput + }{ + "RestXmlEnumPayloadResponse": { + StatusCode: 200, + Body: []byte(`enumvalue`), + ExpectResult: &HttpEnumPayloadOutput{ + Payload: types.StringEnum("enumvalue"), + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + serverURL := "http://localhost:8888/" + client := New(Options{ + HTTPClient: smithyhttp.ClientDoFunc(func(r *http.Request) (*http.Response, error) { + headers := http.Header{} + for k, vs := range c.Header { + for _, v := range vs { + headers.Add(k, v) + } + } + if len(c.BodyMediaType) != 0 && len(headers.Values("Content-Type")) == 0 { + headers.Set("Content-Type", c.BodyMediaType) + } + response := &http.Response{ + StatusCode: c.StatusCode, + Header: headers, + Request: r, + } + if len(c.Body) != 0 { + response.ContentLength = int64(len(c.Body)) + response.Body = ioutil.NopCloser(bytes.NewReader(c.Body)) + } else { + + response.Body = http.NoBody + } + return response, nil + }), + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + IdempotencyTokenProvider: smithyrand.NewUUIDIdempotencyToken(&smithytesting.ByteLoop{}), + Region: "us-west-2", + }) + var params HttpEnumPayloadInput + result, err := client.HttpEnumPayload(context.Background(), ¶ms) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + opts := cmp.Options{ + cmpopts.IgnoreUnexported( + middleware.Metadata{}, + ), + cmp.FilterValues(func(x, y float64) bool { + return math.IsNaN(x) && math.IsNaN(y) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmp.FilterValues(func(x, y float32) bool { + return math.IsNaN(float64(x)) && math.IsNaN(float64(y)) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmpopts.IgnoreTypes(smithydocument.NoSerde{}), + } + if err := smithytesting.CompareValues(c.ExpectResult, result, opts...); err != nil { + t.Errorf("expect c.ExpectResult value match:\n%v", err) + } + }) + } +} diff --git a/internal/protocoltest/restxml/api_op_HttpStringPayload.go b/internal/protocoltest/restxml/api_op_HttpStringPayload.go new file mode 100644 index 00000000000..27eb6c3a46c --- /dev/null +++ b/internal/protocoltest/restxml/api_op_HttpStringPayload.go @@ -0,0 +1,122 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package restxml + +import ( + "context" + "fmt" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +func (c *Client) HttpStringPayload(ctx context.Context, params *HttpStringPayloadInput, optFns ...func(*Options)) (*HttpStringPayloadOutput, error) { + if params == nil { + params = &HttpStringPayloadInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "HttpStringPayload", params, optFns, c.addOperationHttpStringPayloadMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*HttpStringPayloadOutput) + out.ResultMetadata = metadata + return out, nil +} + +type HttpStringPayloadInput struct { + Payload *string + + noSmithyDocumentSerde +} + +type HttpStringPayloadOutput struct { + Payload *string + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationHttpStringPayloadMiddlewares(stack *middleware.Stack, options Options) (err error) { + if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { + return err + } + err = stack.Serialize.Add(&awsRestxml_serializeOpHttpStringPayload{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsRestxml_deserializeOpHttpStringPayload{}, middleware.After) + if err != nil { + return err + } + if err := addProtocolFinalizerMiddlewares(stack, options, "HttpStringPayload"); err != nil { + return fmt.Errorf("add protocol finalizers: %v", err) + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addSetLoggerMiddleware(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addRetryMiddlewares(stack, options); err != nil { + return err + } + if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { + return err + } + if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { + return err + } + if err = addClientUserAgent(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware_opHttpStringPayload(options.Region), middleware.Before); err != nil { + return err + } + if err = awsmiddleware.AddRecursionDetection(stack); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + return nil +} + +func newServiceMetadataMiddleware_opHttpStringPayload(region string) *awsmiddleware.RegisterServiceMetadata { + return &awsmiddleware.RegisterServiceMetadata{ + Region: region, + ServiceID: ServiceID, + OperationName: "HttpStringPayload", + } +} diff --git a/internal/protocoltest/restxml/api_op_HttpStringPayload_test.go b/internal/protocoltest/restxml/api_op_HttpStringPayload_test.go new file mode 100644 index 00000000000..3920abab4ac --- /dev/null +++ b/internal/protocoltest/restxml/api_op_HttpStringPayload_test.go @@ -0,0 +1,202 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package restxml + +import ( + "bytes" + "context" + "github.com/aws/aws-sdk-go-v2/aws" + protocoltesthttp "github.com/aws/aws-sdk-go-v2/internal/protocoltest" + smithydocument "github.com/aws/smithy-go/document" + "github.com/aws/smithy-go/middleware" + smithyprivateprotocol "github.com/aws/smithy-go/private/protocol" + "github.com/aws/smithy-go/ptr" + smithyrand "github.com/aws/smithy-go/rand" + smithytesting "github.com/aws/smithy-go/testing" + smithyhttp "github.com/aws/smithy-go/transport/http" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "io" + "io/ioutil" + "math" + "net/http" + "net/url" + "testing" +) + +func TestClient_HttpStringPayload_awsRestxmlSerialize(t *testing.T) { + cases := map[string]struct { + Params *HttpStringPayloadInput + ExpectMethod string + ExpectURIPath string + ExpectQuery []smithytesting.QueryItem + RequireQuery []string + ForbidQuery []string + ExpectHeader http.Header + RequireHeader []string + ForbidHeader []string + Host *url.URL + BodyMediaType string + BodyAssert func(io.Reader) error + }{ + "RestXmlStringPayloadRequest": { + Params: &HttpStringPayloadInput{ + Payload: ptr.String("rawstring"), + }, + ExpectMethod: "POST", + ExpectURIPath: "/StringPayload", + ExpectQuery: []smithytesting.QueryItem{}, + BodyAssert: func(actual io.Reader) error { + return smithytesting.CompareReaderBytes(actual, []byte(`rawstring`)) + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + actualReq := &http.Request{} + serverURL := "http://localhost:8888/" + if c.Host != nil { + u, err := url.Parse(serverURL) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + u.Path = c.Host.Path + u.RawPath = c.Host.RawPath + u.RawQuery = c.Host.RawQuery + serverURL = u.String() + } + client := New(Options{ + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + HTTPClient: protocoltesthttp.NewClient(), + IdempotencyTokenProvider: smithyrand.NewUUIDIdempotencyToken(&smithytesting.ByteLoop{}), + Region: "us-west-2", + }) + result, err := client.HttpStringPayload(context.Background(), c.Params, func(options *Options) { + options.APIOptions = append(options.APIOptions, func(stack *middleware.Stack) error { + return smithyprivateprotocol.AddCaptureRequestMiddleware(stack, actualReq) + }) + }) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + if e, a := c.ExpectMethod, actualReq.Method; e != a { + t.Errorf("expect %v method, got %v", e, a) + } + if e, a := c.ExpectURIPath, actualReq.URL.RawPath; e != a { + t.Errorf("expect %v path, got %v", e, a) + } + queryItems := smithytesting.ParseRawQuery(actualReq.URL.RawQuery) + smithytesting.AssertHasQuery(t, c.ExpectQuery, queryItems) + smithytesting.AssertHasQueryKeys(t, c.RequireQuery, queryItems) + smithytesting.AssertNotHaveQueryKeys(t, c.ForbidQuery, queryItems) + smithytesting.AssertHasHeader(t, c.ExpectHeader, actualReq.Header) + smithytesting.AssertHasHeaderKeys(t, c.RequireHeader, actualReq.Header) + smithytesting.AssertNotHaveHeaderKeys(t, c.ForbidHeader, actualReq.Header) + if c.BodyAssert != nil { + if err := c.BodyAssert(actualReq.Body); err != nil { + t.Errorf("expect body equal, got %v", err) + } + } + }) + } +} + +func TestClient_HttpStringPayload_awsRestxmlDeserialize(t *testing.T) { + cases := map[string]struct { + StatusCode int + Header http.Header + BodyMediaType string + Body []byte + ExpectResult *HttpStringPayloadOutput + }{ + "RestXmlStringPayloadResponse": { + StatusCode: 200, + Body: []byte(`rawstring`), + ExpectResult: &HttpStringPayloadOutput{ + Payload: ptr.String("rawstring"), + }, + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + serverURL := "http://localhost:8888/" + client := New(Options{ + HTTPClient: smithyhttp.ClientDoFunc(func(r *http.Request) (*http.Response, error) { + headers := http.Header{} + for k, vs := range c.Header { + for _, v := range vs { + headers.Add(k, v) + } + } + if len(c.BodyMediaType) != 0 && len(headers.Values("Content-Type")) == 0 { + headers.Set("Content-Type", c.BodyMediaType) + } + response := &http.Response{ + StatusCode: c.StatusCode, + Header: headers, + Request: r, + } + if len(c.Body) != 0 { + response.ContentLength = int64(len(c.Body)) + response.Body = ioutil.NopCloser(bytes.NewReader(c.Body)) + } else { + + response.Body = http.NoBody + } + return response, nil + }), + APIOptions: []func(*middleware.Stack) error{ + func(s *middleware.Stack) error { + s.Finalize.Clear() + s.Initialize.Remove(`OperationInputValidation`) + return nil + }, + }, + EndpointResolver: EndpointResolverFunc(func(region string, options EndpointResolverOptions) (e aws.Endpoint, err error) { + e.URL = serverURL + e.SigningRegion = "us-west-2" + return e, err + }), + IdempotencyTokenProvider: smithyrand.NewUUIDIdempotencyToken(&smithytesting.ByteLoop{}), + Region: "us-west-2", + }) + var params HttpStringPayloadInput + result, err := client.HttpStringPayload(context.Background(), ¶ms) + if err != nil { + t.Fatalf("expect nil err, got %v", err) + } + if result == nil { + t.Fatalf("expect not nil result") + } + opts := cmp.Options{ + cmpopts.IgnoreUnexported( + middleware.Metadata{}, + ), + cmp.FilterValues(func(x, y float64) bool { + return math.IsNaN(x) && math.IsNaN(y) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmp.FilterValues(func(x, y float32) bool { + return math.IsNaN(float64(x)) && math.IsNaN(float64(y)) + }, cmp.Comparer(func(_, _ interface{}) bool { return true })), + cmpopts.IgnoreTypes(smithydocument.NoSerde{}), + } + if err := smithytesting.CompareValues(c.ExpectResult, result, opts...); err != nil { + t.Errorf("expect c.ExpectResult value match:\n%v", err) + } + }) + } +} diff --git a/internal/protocoltest/restxml/deserializers.go b/internal/protocoltest/restxml/deserializers.go index 1b29d7b6128..ff483e6c005 100644 --- a/internal/protocoltest/restxml/deserializers.go +++ b/internal/protocoltest/restxml/deserializers.go @@ -1423,6 +1423,96 @@ func awsRestxml_deserializeOpHttpBindingsGreetingWithErrorsOutput(v *GreetingWit return nil } +type awsRestxml_deserializeOpHttpEnumPayload struct { +} + +func (*awsRestxml_deserializeOpHttpEnumPayload) ID() string { + return "OperationDeserializer" +} + +func (m *awsRestxml_deserializeOpHttpEnumPayload) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsRestxml_deserializeOpErrorHttpEnumPayload(response, &metadata) + } + output := &HttpEnumPayloadOutput{} + out.Result = output + + err = awsRestxml_deserializeOpDocumentHttpEnumPayloadOutput(output, response.Body, response.ContentLength) + if err != nil { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("failed to deserialize response payload, %w", err)} + } + + return out, metadata, err +} + +func awsRestxml_deserializeOpErrorHttpEnumPayload(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + errorComponents, err := awsxml.GetErrorResponseComponents(errorBody, false) + if err != nil { + return err + } + if reqID := errorComponents.RequestID; len(reqID) != 0 { + awsmiddleware.SetRequestIDMetadata(metadata, reqID) + } + if len(errorComponents.Code) != 0 { + errorCode = errorComponents.Code + } + if len(errorComponents.Message) != 0 { + errorMessage = errorComponents.Message + } + errorBody.Seek(0, io.SeekStart) + switch { + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } +} + +func awsRestxml_deserializeOpDocumentHttpEnumPayloadOutput(v *HttpEnumPayloadOutput, body io.ReadCloser, contentLength int64) error { + if v == nil { + return fmt.Errorf("unsupported deserialization of nil %T", v) + } + var buf bytes.Buffer + if contentLength > 0 { + buf.Grow(int(contentLength)) + } else { + buf.Grow(512) + } + + _, err := buf.ReadFrom(body) + if err != nil { + return err + } + if buf.Len() > 0 { + v.Payload = types.StringEnum(buf.Bytes()) + } + return nil +} + type awsRestxml_deserializeOpHttpPayloadTraits struct { } @@ -2892,6 +2982,96 @@ func awsRestxml_deserializeOpHttpBindingsHttpResponseCodeOutput(v *HttpResponseC return nil } +type awsRestxml_deserializeOpHttpStringPayload struct { +} + +func (*awsRestxml_deserializeOpHttpStringPayload) ID() string { + return "OperationDeserializer" +} + +func (m *awsRestxml_deserializeOpHttpStringPayload) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsRestxml_deserializeOpErrorHttpStringPayload(response, &metadata) + } + output := &HttpStringPayloadOutput{} + out.Result = output + + err = awsRestxml_deserializeOpDocumentHttpStringPayloadOutput(output, response.Body, response.ContentLength) + if err != nil { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("failed to deserialize response payload, %w", err)} + } + + return out, metadata, err +} + +func awsRestxml_deserializeOpErrorHttpStringPayload(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + errorComponents, err := awsxml.GetErrorResponseComponents(errorBody, false) + if err != nil { + return err + } + if reqID := errorComponents.RequestID; len(reqID) != 0 { + awsmiddleware.SetRequestIDMetadata(metadata, reqID) + } + if len(errorComponents.Code) != 0 { + errorCode = errorComponents.Code + } + if len(errorComponents.Message) != 0 { + errorMessage = errorComponents.Message + } + errorBody.Seek(0, io.SeekStart) + switch { + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } +} + +func awsRestxml_deserializeOpDocumentHttpStringPayloadOutput(v *HttpStringPayloadOutput, body io.ReadCloser, contentLength int64) error { + if v == nil { + return fmt.Errorf("unsupported deserialization of nil %T", v) + } + var buf bytes.Buffer + if contentLength > 0 { + buf.Grow(int(contentLength)) + } else { + buf.Grow(512) + } + + _, err := buf.ReadFrom(body) + if err != nil { + return err + } + if buf.Len() > 0 { + v.Payload = ptr.String(buf.String()) + } + return nil +} + type awsRestxml_deserializeOpIgnoreQueryParamsInResponse struct { } diff --git a/internal/protocoltest/restxml/generated.json b/internal/protocoltest/restxml/generated.json index 26998e88a5b..ea5b928a8f1 100644 --- a/internal/protocoltest/restxml/generated.json +++ b/internal/protocoltest/restxml/generated.json @@ -37,6 +37,8 @@ "api_op_FractionalSeconds_test.go", "api_op_GreetingWithErrors.go", "api_op_GreetingWithErrors_test.go", + "api_op_HttpEnumPayload.go", + "api_op_HttpEnumPayload_test.go", "api_op_HttpPayloadTraits.go", "api_op_HttpPayloadTraitsWithMediaType.go", "api_op_HttpPayloadTraitsWithMediaType_test.go", @@ -65,6 +67,8 @@ "api_op_HttpRequestWithLabels_test.go", "api_op_HttpResponseCode.go", "api_op_HttpResponseCode_test.go", + "api_op_HttpStringPayload.go", + "api_op_HttpStringPayload_test.go", "api_op_IgnoreQueryParamsInResponse.go", "api_op_IgnoreQueryParamsInResponse_test.go", "api_op_InputAndOutputWithHeaders.go", diff --git a/internal/protocoltest/restxml/serializers.go b/internal/protocoltest/restxml/serializers.go index f4b973c2490..cce329e2254 100644 --- a/internal/protocoltest/restxml/serializers.go +++ b/internal/protocoltest/restxml/serializers.go @@ -1031,6 +1031,70 @@ func awsRestxml_serializeOpHttpBindingsGreetingWithErrorsInput(v *GreetingWithEr return nil } +type awsRestxml_serializeOpHttpEnumPayload struct { +} + +func (*awsRestxml_serializeOpHttpEnumPayload) ID() string { + return "OperationSerializer" +} + +func (m *awsRestxml_serializeOpHttpEnumPayload) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*HttpEnumPayloadInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + opPath, opQuery := httpbinding.SplitURI("/EnumPayload") + request.URL.Path = smithyhttp.JoinPath(request.URL.Path, opPath) + request.URL.RawQuery = smithyhttp.JoinRawQuery(request.URL.RawQuery, opQuery) + request.Method = "POST" + var restEncoder *httpbinding.Encoder + if request.URL.RawPath == "" { + restEncoder, err = httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + } else { + request.URL.RawPath = smithyhttp.JoinPath(request.URL.RawPath, opPath) + restEncoder, err = httpbinding.NewEncoderWithRawPath(request.URL.Path, request.URL.RawPath, request.URL.RawQuery, request.Header) + } + + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if !restEncoder.HasHeader("Content-Type") { + ctx = smithyhttp.SetIsContentTypeDefaultValue(ctx, true) + restEncoder.SetHeader("Content-Type").String("text/plain") + } + + if len(input.Payload) > 0 { + payload := strings.NewReader(string(input.Payload)) + if request, err = request.SetStream(payload); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + } + + if request.Request, err = restEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + return next.HandleSerialize(ctx, in) +} +func awsRestxml_serializeOpHttpBindingsHttpEnumPayloadInput(v *HttpEnumPayloadInput, encoder *httpbinding.Encoder) error { + if v == nil { + return fmt.Errorf("unsupported serialization of nil %T", v) + } + + return nil +} + type awsRestxml_serializeOpHttpPayloadTraits struct { } @@ -2146,6 +2210,70 @@ func awsRestxml_serializeOpHttpBindingsHttpResponseCodeInput(v *HttpResponseCode return nil } +type awsRestxml_serializeOpHttpStringPayload struct { +} + +func (*awsRestxml_serializeOpHttpStringPayload) ID() string { + return "OperationSerializer" +} + +func (m *awsRestxml_serializeOpHttpStringPayload) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*HttpStringPayloadInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + opPath, opQuery := httpbinding.SplitURI("/StringPayload") + request.URL.Path = smithyhttp.JoinPath(request.URL.Path, opPath) + request.URL.RawQuery = smithyhttp.JoinRawQuery(request.URL.RawQuery, opQuery) + request.Method = "POST" + var restEncoder *httpbinding.Encoder + if request.URL.RawPath == "" { + restEncoder, err = httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + } else { + request.URL.RawPath = smithyhttp.JoinPath(request.URL.RawPath, opPath) + restEncoder, err = httpbinding.NewEncoderWithRawPath(request.URL.Path, request.URL.RawPath, request.URL.RawQuery, request.Header) + } + + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if !restEncoder.HasHeader("Content-Type") { + ctx = smithyhttp.SetIsContentTypeDefaultValue(ctx, true) + restEncoder.SetHeader("Content-Type").String("text/plain") + } + + if input.Payload != nil { + payload := strings.NewReader(*input.Payload) + if request, err = request.SetStream(payload); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + } + + if request.Request, err = restEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + return next.HandleSerialize(ctx, in) +} +func awsRestxml_serializeOpHttpBindingsHttpStringPayloadInput(v *HttpStringPayloadInput, encoder *httpbinding.Encoder) error { + if v == nil { + return fmt.Errorf("unsupported serialization of nil %T", v) + } + + return nil +} + type awsRestxml_serializeOpIgnoreQueryParamsInResponse struct { } diff --git a/internal/protocoltest/restxml/types/enums.go b/internal/protocoltest/restxml/types/enums.go index 6652e863c7a..a9a2312d5b7 100644 --- a/internal/protocoltest/restxml/types/enums.go +++ b/internal/protocoltest/restxml/types/enums.go @@ -2,6 +2,22 @@ package types +type StringEnum string + +// Enum values for StringEnum +const ( + StringEnumV StringEnum = "enumvalue" +) + +// Values returns all known values for StringEnum. Note that this can be expanded +// in the future, and so it is only as up to date as the client. The ordering of +// this slice is not guaranteed to be stable across updates. +func (StringEnum) Values() []StringEnum { + return []StringEnum{ + "enumvalue", + } +} + type FooEnum string // Enum values for FooEnum