Skip to content

Commit

Permalink
private/model/api: Fix SDK's unmarshaling of unmodeled response paylo…
Browse files Browse the repository at this point in the history
…ad (#2340)

Fixes the SDK's unmarshaling of API operation response payloads for
operations that are unmodeled. Prevents the SDK due to unexpected
response payloads causing errors in the API protocol unmarshaler.

Fix #2332
  • Loading branch information
jasdel authored Dec 11, 2018
1 parent fe08bc8 commit b878eb0
Showing 155 changed files with 2,240 additions and 1,779 deletions.
4 changes: 2 additions & 2 deletions models/protocol_tests/generate.go
Original file line number Diff line number Diff line change
@@ -263,8 +263,8 @@ func Test{{ .OpName }}(t *testing.T) {
{{ end }}
// unmarshal response
{{ .TestCase.TestSuite.API.ProtocolPackage }}.UnmarshalMeta(req)
{{ .TestCase.TestSuite.API.ProtocolPackage }}.Unmarshal(req)
req.Handlers.UnmarshalMeta.Run(req)
req.Handlers.Unmarshal.Run(req)
if req.Error != nil {
t.Errorf("expect not error, got %v", req.Error)
}
64 changes: 62 additions & 2 deletions models/protocol_tests/output/json.json
Original file line number Diff line number Diff line change
@@ -413,11 +413,11 @@
}
},
"cases": [
{
{
"given": {
"output": {
"shape": "OutputShape"
},
},
"name": "OperationName"
},
"result": {
@@ -431,5 +431,65 @@
}
}
]
},
{
"description": "unmodeled non-json response payload",
"metadata": {
"protocol": "json"
},
"shapes": {
"OutputShape": {
"type": "structure",
"members": {
}
}
},
"cases": [
{
"given": {
"output": {
"shape": "OutputShape"
},
"name": "OperationName"
},
"result": {
},
"response": {
"status_code": 200,
"headers": {},
"body": "success"
}
},
{
"given": {
"output": {
"shape": "OutputShape"
},
"name": "OperationName"
},
"result": {
},
"response": {
"status_code": 200,
"headers": {},
"body": "\"success\""
}
},
{
"given": {
"output": {
"shape": "OutputShape"
},
"name": "OperationName"
},
"result": {
},
"response": {
"status_code": 200,
"headers": {},
"body": "{}"
}
}
]
}
]
68 changes: 37 additions & 31 deletions private/model/api/api.go
Original file line number Diff line number Diff line change
@@ -14,6 +14,9 @@ import (
"unicode"
)

// SDKImportRoot is the root import path of the SDK.
const SDKImportRoot = "github.com/aws/aws-sdk-go"

// An API defines a service API's definition. and logic to serialize the definition.
type API struct {
Metadata Metadata
@@ -239,9 +242,7 @@ func (a *API) ShapeListErrors() []*Shape {

// resetImports resets the import map to default values.
func (a *API) resetImports() {
a.imports = map[string]bool{
"github.com/aws/aws-sdk-go/aws": true,
}
a.imports = map[string]bool{}
}

// importsGoCode returns the generated Go import code.
@@ -293,22 +294,28 @@ var tplAPI = template.Must(template.New("api").Parse(`
{{ end }}
`))

// AddImport adds the import path to the generated file's import.
func (a *API) AddImport(v string) error {
a.imports[v] = true
return nil
}

// AddSDKImport adds a SDK package import to the generated file's import.
func (a *API) AddSDKImport(v ...string) error {
e := make([]string, 0, 5)
e = append(e, SDKImportRoot)
e = append(e, v...)

a.imports[path.Join(e...)] = true
return nil
}

// APIGoCode renders the API in Go code. Returning it as a string
func (a *API) APIGoCode() string {
a.resetImports()
a.imports["github.com/aws/aws-sdk-go/aws/awsutil"] = true
a.imports["github.com/aws/aws-sdk-go/aws/request"] = true
if a.OperationHasOutputPlaceholder() {
a.imports["github.com/aws/aws-sdk-go/private/protocol/"+a.ProtocolPackage()] = true
a.imports["github.com/aws/aws-sdk-go/private/protocol"] = true
}

for _, op := range a.Operations {
if op.AuthType == "none" {
a.imports["github.com/aws/aws-sdk-go/aws/credentials"] = true
break
}
}
a.AddSDKImport("aws")
a.AddSDKImport("aws/awsutil")
a.AddSDKImport("aws/request")

var buf bytes.Buffer
err := tplAPI.Execute(&buf, a)
@@ -624,18 +631,19 @@ func (a *API) ServicePackageDoc() string {
// ServiceGoCode renders service go code. Returning it as a string.
func (a *API) ServiceGoCode() string {
a.resetImports()
a.imports["github.com/aws/aws-sdk-go/aws/client"] = true
a.imports["github.com/aws/aws-sdk-go/aws/client/metadata"] = true
a.imports["github.com/aws/aws-sdk-go/aws/request"] = true
a.AddSDKImport("aws")
a.AddSDKImport("aws/client")
a.AddSDKImport("aws/client/metadata")
a.AddSDKImport("aws/request")
if a.Metadata.SignatureVersion == "v2" {
a.imports["github.com/aws/aws-sdk-go/private/signer/v2"] = true
a.imports["github.com/aws/aws-sdk-go/aws/corehandlers"] = true
a.AddSDKImport("private/signer/v2")
a.AddSDKImport("aws/corehandlers")
} else {
a.imports["github.com/aws/aws-sdk-go/aws/signer/v4"] = true
a.AddSDKImport("aws/signer/v4")
}
a.imports["github.com/aws/aws-sdk-go/private/protocol/"+a.ProtocolPackage()] = true
a.AddSDKImport("private/protocol", a.ProtocolPackage())
if a.EndpointDiscoveryOp != nil {
a.imports["github.com/aws/aws-sdk-go/aws/crr"] = true
a.AddSDKImport("aws/crr")
}

var buf bytes.Buffer
@@ -664,8 +672,8 @@ func (a *API) ExampleGoCode() string {
"bytes",
"fmt",
"time",
"github.com/aws/aws-sdk-go/aws",
"github.com/aws/aws-sdk-go/aws/session",
SDKImportRoot+"/aws",
SDKImportRoot+"/aws/session",
a.ImportPath(),
)
for k := range imports {
@@ -741,11 +749,9 @@ var _ {{ .StructName }}API = (*{{ .PackageName }}.{{ .StructName }})(nil)
// package than the service API's package.
func (a *API) InterfaceGoCode() string {
a.resetImports()
a.imports = map[string]bool{
"github.com/aws/aws-sdk-go/aws": true,
"github.com/aws/aws-sdk-go/aws/request": true,
a.ImportPath(): true,
}
a.AddSDKImport("aws")
a.AddSDKImport("aws/request")
a.AddImport(a.ImportPath())

var buf bytes.Buffer
err := tplInterface.Execute(&buf, a)
2 changes: 1 addition & 1 deletion private/model/api/customization_passes.go
Original file line number Diff line number Diff line change
@@ -181,7 +181,7 @@ func mergeServicesCustomizations(a *API) {

for n := range a.Shapes {
if _, ok := serviceAPI.Shapes[n]; ok {
a.Shapes[n].resolvePkg = "github.com/aws/aws-sdk-go/service/" + info.dstName
a.Shapes[n].resolvePkg = SDKImportRoot+"/service/" + info.dstName
}
}
}
2 changes: 1 addition & 1 deletion private/model/api/endpoint_trait.go
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import (
)

func setupEndpointHostPrefix(op *Operation) {
op.API.imports["github.com/aws/aws-sdk-go/private/protocol"] = true
op.API.AddSDKImport("private/protocol")

buildHandler := fmt.Sprintf("protocol.NewHostPrefixHandler(%q, ",
op.Endpoint.HostPrefix)
50 changes: 26 additions & 24 deletions private/model/api/eventstream.go
Original file line number Diff line number Diff line change
@@ -233,14 +233,15 @@ func updateEventPayloadRef(parent *Shape) {

func renderEventStreamAPIShape(w io.Writer, s *Shape) error {
// Imports needed by the EventStream APIs.
s.API.imports["fmt"] = true
s.API.imports["bytes"] = true
s.API.imports["io"] = true
s.API.imports["sync"] = true
s.API.imports["sync/atomic"] = true
s.API.imports["github.com/aws/aws-sdk-go/aws/awserr"] = true
s.API.imports["github.com/aws/aws-sdk-go/private/protocol/eventstream"] = true
s.API.imports["github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi"] = true
s.API.AddImport("fmt")
s.API.AddImport("bytes")
s.API.AddImport("io")
s.API.AddImport("sync")
s.API.AddImport("sync/atomic")
s.API.AddSDKImport("aws")
s.API.AddSDKImport("aws/awserr")
s.API.AddSDKImport("private/protocol/eventstream")
s.API.AddSDKImport("private/protocol/eventstream/eventstreamapi")

return eventStreamAPIShapeTmpl.Execute(w, s)
}
@@ -705,21 +706,22 @@ func (a *API) APIEventStreamTestGoCode() string {
var buf bytes.Buffer

a.resetImports()
a.imports["bytes"] = true
a.imports["io/ioutil"] = true
a.imports["net/http"] = true
a.imports["reflect"] = true
a.imports["testing"] = true
a.imports["time"] = true
a.imports["github.com/aws/aws-sdk-go/aws/corehandlers"] = true
a.imports["github.com/aws/aws-sdk-go/aws/request"] = true
a.imports["github.com/aws/aws-sdk-go/aws/awserr"] = true
a.imports["github.com/aws/aws-sdk-go/awstesting/unit"] = true
a.imports["github.com/aws/aws-sdk-go/private/protocol"] = true
a.imports["github.com/aws/aws-sdk-go/private/protocol/"+a.ProtocolPackage()] = true
a.imports["github.com/aws/aws-sdk-go/private/protocol/eventstream"] = true
a.imports["github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi"] = true
a.imports["github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamtest"] = true
a.AddImport("bytes")
a.AddImport("io/ioutil")
a.AddImport("net/http")
a.AddImport("reflect")
a.AddImport("testing")
a.AddImport("time")
a.AddSDKImport("aws")
a.AddSDKImport("aws/corehandlers")
a.AddSDKImport("aws/request")
a.AddSDKImport("aws/awserr")
a.AddSDKImport("awstesting/unit")
a.AddSDKImport("private/protocol")
a.AddSDKImport("private/protocol/", a.ProtocolPackage())
a.AddSDKImport("private/protocol/eventstream")
a.AddSDKImport("private/protocol/eventstream/eventstreamapi")
a.AddSDKImport("private/protocol/eventstream/eventstreamtest")

unused := `
var _ time.Time
@@ -843,7 +845,7 @@ var eventStreamTestTmpl = template.Must(
"ValueForType": valueForType,
"HasNonBlobPayloadMembers": eventHasNonBlobPayloadMembers,
"SetEventHeaderValueForType": setEventHeaderValueForType,
"Map": templateMap,
"Map": templateMap,
"OptionalAddInt": func(do bool, a, b int) int {
if !do {
return a
8 changes: 4 additions & 4 deletions private/model/api/example_test.go
Original file line number Diff line number Diff line change
@@ -220,10 +220,10 @@ import (
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/fooservice"
"` + SDKImportRoot + `/aws"
"` + SDKImportRoot + `/aws/awserr"
"` + SDKImportRoot + `/aws/session"
"` + SDKImportRoot + `/service/fooservice"
)
var _ time.Duration
20 changes: 6 additions & 14 deletions private/model/api/examples_builder.go
Original file line number Diff line number Diff line change
@@ -2,11 +2,6 @@

package api

import (
"bytes"
"fmt"
)

type examplesBuilder interface {
BuildShape(*ShapeRef, map[string]interface{}, bool) string
BuildList(string, string, *ShapeRef, []interface{}) string
@@ -20,16 +15,13 @@ type defaultExamplesBuilder struct {
}

func (builder defaultExamplesBuilder) Imports(a *API) string {
buf := bytes.NewBuffer(nil)
buf.WriteString(`"fmt"
return `"fmt"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
`)

buf.WriteString(fmt.Sprintf("\"%s/%s\"", "github.com/aws/aws-sdk-go/service", a.PackageName()))
return buf.String()
"` + SDKImportRoot + `/aws"
"` + SDKImportRoot + `/aws/awserr"
"` + SDKImportRoot + `/aws/session"
"` + SDKImportRoot + `/service/` + a.PackageName() + `"
`
}
22 changes: 7 additions & 15 deletions private/model/api/examples_builder_customizations.go
Original file line number Diff line number Diff line change
@@ -2,27 +2,19 @@

package api

import (
"bytes"
"fmt"
)

type wafregionalExamplesBuilder struct {
defaultExamplesBuilder
}

func (builder wafregionalExamplesBuilder) Imports(a *API) string {
buf := bytes.NewBuffer(nil)
buf.WriteString(`"fmt"
return `"fmt"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/waf"
`)

buf.WriteString(fmt.Sprintf("\"%s/%s\"", "github.com/aws/aws-sdk-go/service", a.PackageName()))
return buf.String()
"` + SDKImportRoot + `/aws"
"` + SDKImportRoot + `/aws/awserr"
"` + SDKImportRoot + `/aws/session"
"` + SDKImportRoot + `/service/waf"
"` + SDKImportRoot + `/service/` + a.PackageName() + `"
`
}
Loading

0 comments on commit b878eb0

Please sign in to comment.