diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index cdedeb2e4..600ebec68 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -13,11 +13,27 @@ }, { "ImportPath": "github.com/awslabs/aws-sdk-go/aws", - "Rev": "8309368a6833a20be7f53e05bd57493742a2ed96" + "Rev": "d67a47db2971c58a865e3ed3d5d4ee317477ac10" + }, + { + "ImportPath": "github.com/awslabs/aws-sdk-go/internal/endpoints", + "Rev": "d67a47db2971c58a865e3ed3d5d4ee317477ac10" + }, + { + "ImportPath": "github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil", + "Rev": "d67a47db2971c58a865e3ed3d5d4ee317477ac10" + }, + { + "ImportPath": "github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc", + "Rev": "d67a47db2971c58a865e3ed3d5d4ee317477ac10" + }, + { + "ImportPath": "github.com/awslabs/aws-sdk-go/internal/signer/v4", + "Rev": "d67a47db2971c58a865e3ed3d5d4ee317477ac10" }, { "ImportPath": "github.com/awslabs/aws-sdk-go/service/dynamodb", - "Rev": "8309368a6833a20be7f53e05bd57493742a2ed96" + "Rev": "d67a47db2971c58a865e3ed3d5d4ee317477ac10" }, { "ImportPath": "github.com/coreos/go-etcd/etcd", diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.go new file mode 100644 index 000000000..590510112 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.go @@ -0,0 +1,27 @@ +package endpoints + +//go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go + +import "strings" + +func EndpointForRegion(svcName, region string) (endpoint, signingRegion string) { + derivedKeys := []string{ + region + "/" + svcName, + region + "/*", + "*/" + svcName, + "*/*", + } + + for _, key := range derivedKeys { + if val, ok := endpointsMap.Endpoints[key]; ok { + ep := val.Endpoint + ep = strings.Replace(ep, "{region}", region, -1) + ep = strings.Replace(ep, "{service}", svcName, -1) + + endpoint = ep + signingRegion = val.SigningRegion + return + } + } + return +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.json b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.json new file mode 100644 index 000000000..4c588090a --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints.json @@ -0,0 +1,77 @@ +{ + "version": 2, + "endpoints": { + "*/*": { + "endpoint": "{service}.{region}.amazonaws.com" + }, + "cn-north-1/*": { + "endpoint": "{service}.{region}.amazonaws.com.cn", + "signatureVersion": "v4" + }, + "us-gov-west-1/iam": { + "endpoint": "iam.us-gov.amazonaws.com" + }, + "us-gov-west-1/sts": { + "endpoint": "sts.us-gov-west-1.amazonaws.com" + }, + "us-gov-west-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "*/cloudfront": { + "endpoint": "cloudfront.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/cloudsearchdomain": { + "endpoint": "", + "signingRegion": "us-east-1" + }, + "*/iam": { + "endpoint": "iam.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/importexport": { + "endpoint": "importexport.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/route53": { + "endpoint": "route53.amazonaws.com", + "signingRegion": "us-east-1" + }, + "*/sts": { + "endpoint": "sts.amazonaws.com", + "signingRegion": "us-east-1" + }, + "us-east-1/sdb": { + "endpoint": "sdb.amazonaws.com", + "signingRegion": "us-east-1" + }, + "us-east-1/s3": { + "endpoint": "s3.amazonaws.com" + }, + "us-west-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "us-west-2/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "eu-west-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "ap-southeast-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "ap-southeast-2/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "ap-northeast-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "sa-east-1/s3": { + "endpoint": "s3-{region}.amazonaws.com" + }, + "eu-central-1/s3": { + "endpoint": "{service}.{region}.amazonaws.com", + "signatureVersion": "v4" + } + } +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_map.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_map.go new file mode 100644 index 000000000..637fcbe43 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_map.go @@ -0,0 +1,89 @@ +package endpoints + +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +type endpointStruct struct { + Version int + Endpoints map[string]endpointEntry +} + +type endpointEntry struct { + Endpoint string + SigningRegion string +} + +var endpointsMap = endpointStruct{ + Version: 2, + Endpoints: map[string]endpointEntry{ + "*/*": endpointEntry{ + Endpoint: "{service}.{region}.amazonaws.com", + }, + "*/cloudfront": endpointEntry{ + Endpoint: "cloudfront.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/cloudsearchdomain": endpointEntry{ + Endpoint: "", + SigningRegion: "us-east-1", + }, + "*/iam": endpointEntry{ + Endpoint: "iam.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/importexport": endpointEntry{ + Endpoint: "importexport.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/route53": endpointEntry{ + Endpoint: "route53.amazonaws.com", + SigningRegion: "us-east-1", + }, + "*/sts": endpointEntry{ + Endpoint: "sts.amazonaws.com", + SigningRegion: "us-east-1", + }, + "ap-northeast-1/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + "ap-southeast-1/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + "ap-southeast-2/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + "cn-north-1/*": endpointEntry{ + Endpoint: "{service}.{region}.amazonaws.com.cn", + }, + "eu-central-1/s3": endpointEntry{ + Endpoint: "{service}.{region}.amazonaws.com", + }, + "eu-west-1/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + "sa-east-1/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + "us-east-1/s3": endpointEntry{ + Endpoint: "s3.amazonaws.com", + }, + "us-east-1/sdb": endpointEntry{ + Endpoint: "sdb.amazonaws.com", + SigningRegion: "us-east-1", + }, + "us-gov-west-1/iam": endpointEntry{ + Endpoint: "iam.us-gov.amazonaws.com", + }, + "us-gov-west-1/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + "us-gov-west-1/sts": endpointEntry{ + Endpoint: "sts.us-gov-west-1.amazonaws.com", + }, + "us-west-1/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + "us-west-2/s3": endpointEntry{ + Endpoint: "s3-{region}.amazonaws.com", + }, + }, +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_test.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_test.go new file mode 100644 index 000000000..8af65879d --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/endpoints/endpoints_test.go @@ -0,0 +1,28 @@ +package endpoints + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGlobalEndpoints(t *testing.T) { + region := "mock-region-1" + svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts"} + + for _, name := range svcs { + ep, sr := EndpointForRegion(name, region) + assert.Equal(t, name+".amazonaws.com", ep) + assert.Equal(t, "us-east-1", sr) + } +} + +func TestServicesInCN(t *testing.T) { + region := "cn-north-1" + svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "s3"} + + for _, name := range svcs { + ep, _ := EndpointForRegion(name, region) + assert.Equal(t, name+"."+region+".amazonaws.com.cn", ep) + } +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/build.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/build.go new file mode 100644 index 000000000..74fee5163 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/build.go @@ -0,0 +1,185 @@ +package jsonutil + +import ( + "bytes" + "encoding/base64" + "fmt" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +func BuildJSON(v interface{}) ([]byte, error) { + var buf bytes.Buffer + + err := buildAny(reflect.ValueOf(v), &buf, "") + return buf.Bytes(), err +} + +func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + value = reflect.Indirect(value) + if !value.IsValid() { + return nil + } + + vtype := value.Type() + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if _, ok := value.Interface().(time.Time); !ok { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("SDKShapeTraits"); ok { + tag = field.Tag + } + return buildStruct(value, buf, tag) + case "list": + return buildList(value, buf, tag) + case "map": + return buildMap(value, buf, tag) + default: + return buildScalar(value, buf, tag) + } +} + +func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + if !value.IsValid() { + return nil + } + + buf.WriteString("{") + + t, fields := value.Type(), []*reflect.StructField{} + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + member := value.FieldByName(field.Name) + if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice) && member.IsNil() { + continue // ignore unset fields + } + if c := field.Name[0:1]; strings.ToLower(c) == c { + continue // ignore unexported fields + } + if field.Tag.Get("location") != "" { + continue // ignore non-body elements + } + + fields = append(fields, &field) + } + + for i, field := range fields { + member := value.FieldByName(field.Name) + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + buf.WriteString(fmt.Sprintf("%q:", name)) + + err := buildAny(member, buf, field.Tag) + if err != nil { + return err + } + + if i < len(fields)-1 { + buf.WriteString(",") + } + } + + buf.WriteString("}") + + return nil +} + +func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("[") + + for i := 0; i < value.Len(); i++ { + buildAny(value.Index(i), buf, "") + + if i < value.Len()-1 { + buf.WriteString(",") + } + } + + buf.WriteString("]") + + return nil +} + +func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("{") + + keys := make([]string, value.Len()) + for i, n := range value.MapKeys() { + keys[i] = n.String() + } + sort.Strings(keys) + + for i, k := range keys { + buf.WriteString(fmt.Sprintf("%q:", k)) + buildAny(value.MapIndex(reflect.ValueOf(k)), buf, "") + + if i < len(keys)-1 { + buf.WriteString(",") + } + } + + buf.WriteString("}") + + return nil +} + +func buildScalar(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + switch converted := value.Interface().(type) { + case string: + writeString(converted, buf) + case []byte: + if !value.IsNil() { + buf.WriteString(fmt.Sprintf("%q", base64.StdEncoding.EncodeToString(converted))) + } + case bool: + buf.WriteString(strconv.FormatBool(converted)) + case int64: + buf.WriteString(strconv.FormatInt(converted, 10)) + case float64: + buf.WriteString(strconv.FormatFloat(converted, 'f', -1, 64)) + case time.Time: + buf.WriteString(strconv.FormatInt(converted.UTC().Unix(), 10)) + default: + return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type()) + } + return nil +} + +func writeString(s string, buf *bytes.Buffer) { + buf.WriteByte('"') + for _, r := range s { + if r == '"' { + buf.WriteString(`\"`) + } else if r < 32 { + fmt.Fprintf(buf, "\\u%0.4x", r) + } else { + buf.WriteRune(r) + } + } + buf.WriteByte('"') +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/build_test.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/build_test.go new file mode 100644 index 000000000..fc27e7c1e --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/build_test.go @@ -0,0 +1,100 @@ +package jsonutil_test + +import ( + "encoding/json" + "testing" + "time" + + "github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil" + "github.com/stretchr/testify/assert" +) + +func S(s string) *string { + return &s +} + +func D(s int64) *int64 { + return &s +} + +func F(s float64) *float64 { + return &s +} + +func T(s time.Time) *time.Time { + return &s +} + +type J struct { + S *string + SS []string + D *int64 + F *float64 + T *time.Time +} + +var jsonTests = []struct { + in interface{} + out string + err string +}{ + { + J{}, + `{}`, + ``, + }, + { + J{ + S: S("str"), + SS: []string{"A", "B", "C"}, + D: D(123), + F: F(4.56), + T: T(time.Unix(987, 0)), + }, + `{"S":"str","SS":["A","B","C"],"D":123,"F":4.56,"T":987}`, + ``, + }, + { + J{ + S: S(`"''"`), + }, + `{"S":"\"''\""}`, + ``, + }, + { + J{ + S: S("\x00føø\u00FF"), + }, + `{"S":"\u0000føøÿ"}`, + ``, + }, +} + +func TestBuildJSON(t *testing.T) { + for _, test := range jsonTests { + out, err := jsonutil.BuildJSON(test.in) + if test.err != "" { + assert.Error(t, err) + assert.Contains(t, err.Error(), test.err) + } else { + assert.NoError(t, err) + assert.Equal(t, string(out), test.out) + } + } +} + +func BenchmarkBuildJSON(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range jsonTests { + jsonutil.BuildJSON(test.in) + } + } +} + +func BenchmarkStdlibJSON(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range jsonTests { + json.Marshal(test.in) + } + } +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/unmarshal.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/unmarshal.go new file mode 100644 index 000000000..d7856f3ad --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil/unmarshal.go @@ -0,0 +1,220 @@ +package jsonutil + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "reflect" + "strings" + "time" +) + +func UnmarshalJSON(v interface{}, stream io.Reader) error { + var out interface{} + + b, err := ioutil.ReadAll(stream) + if err != nil { + return err + } + + if len(b) == 0 { + return nil + } + + if err := json.Unmarshal(b, &out); err != nil { + return err + } + + return unmarshalAny(reflect.ValueOf(v), out, "") +} + +func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error { + vtype := value.Type() + if vtype.Kind() == reflect.Ptr { + vtype = vtype.Elem() // check kind of actual element type + } + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if _, ok := value.Interface().(*time.Time); !ok { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("SDKShapeTraits"); ok { + tag = field.Tag + } + return unmarshalStruct(value, data, tag) + case "list": + return unmarshalList(value, data, tag) + case "map": + return unmarshalMap(value, data, tag) + default: + return unmarshalScalar(value, data, tag) + } +} + +func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a structure (%#v)", data) + } + + t := value.Type() + if value.Kind() == reflect.Ptr { + if value.IsNil() { // create the structure if it's nil + s := reflect.New(value.Type().Elem()) + value.Set(s) + value = s + } + + value = value.Elem() + t = t.Elem() + } + + // unwrap any payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := t.FieldByName(payload) + return unmarshalAny(value.FieldByName(payload), data, field.Tag) + } + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if c := field.Name[0:1]; strings.ToLower(c) == c { + continue // ignore unexported fields + } + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + member := value.FieldByName(field.Name) + err := unmarshalAny(member, mapData[name], field.Tag) + if err != nil { + return err + } + } + return nil +} + +func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + listData, ok := data.([]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a list (%#v)", data) + } + + if value.IsNil() { + l := len(listData) + value.Set(reflect.MakeSlice(value.Type(), l, l)) + } + + for i, c := range listData { + err := unmarshalAny(value.Index(i), c, "") + if err != nil { + return err + } + } + + return nil +} + +func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a map (%#v)", data) + } + + t := value.Type() + if value.Kind() == reflect.Ptr { + t = t.Elem() + if value.IsNil() { + value.Set(reflect.New(t)) + value.Elem().Set(reflect.MakeMap(t)) + } + + value = value.Elem() + } + + for k, v := range mapData { + kvalue := reflect.ValueOf(k) + vvalue := reflect.New(value.Type().Elem()).Elem() + + unmarshalAny(vvalue, v, "") + value.SetMapIndex(kvalue, vvalue) + } + + return nil +} + +func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error { + errf := func() error { + return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type()) + } + + switch d := data.(type) { + case nil: + return nil // nothing to do here + case string: + switch value.Interface().(type) { + case *string: + value.Set(reflect.ValueOf(&d)) + case []byte: + b, err := base64.StdEncoding.DecodeString(d) + if err != nil { + return err + } + value.Set(reflect.ValueOf(b)) + default: + return errf() + } + case float64: + switch value.Interface().(type) { + case *int64: + di := int64(d) + value.Set(reflect.ValueOf(&di)) + case *float64: + value.Set(reflect.ValueOf(&d)) + case *time.Time: + t := time.Unix(int64(d), 0).UTC() + value.Set(reflect.ValueOf(&t)) + default: + return errf() + } + case bool: + switch value.Interface().(type) { + case *bool: + value.Set(reflect.ValueOf(&d)) + default: + return errf() + } + default: + return fmt.Errorf("unsupported JSON value (%v)", data) + } + return nil +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/build_test.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/build_test.go new file mode 100644 index 000000000..739af8d61 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/build_test.go @@ -0,0 +1,1049 @@ +package jsonrpc_test + +import ( + "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc" + "github.com/awslabs/aws-sdk-go/internal/signer/v4" + + "bytes" + "encoding/json" + "encoding/xml" + "github.com/awslabs/aws-sdk-go/internal/protocol/xml/xmlutil" + "github.com/awslabs/aws-sdk-go/internal/util" + "github.com/stretchr/testify/assert" + "io" + "io/ioutil" + "net/http" + "net/url" + "testing" + "time" +) + +var _ bytes.Buffer // always import bytes +var _ http.Request +var _ json.Marshaler +var _ time.Time +var _ xmlutil.XMLNode +var _ xml.Attr +var _ = ioutil.Discard +var _ = util.Trim("") +var _ = url.Values{} +var _ = io.EOF + +// InputService1ProtocolTest is a client for InputService1ProtocolTest. +type InputService1ProtocolTest struct { + *aws.Service +} + +// New returns a new InputService1ProtocolTest client. +func NewInputService1ProtocolTest(config *aws.Config) *InputService1ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "inputservice1protocoltest", + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &InputService1ProtocolTest{service} +} + +// newRequest creates a new request for a InputService1ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService1ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// InputService1TestCaseOperation1Request generates a request for the InputService1TestCaseOperation1 operation. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1Request(input *InputService1TestShapeInputShape) (req *aws.Request, output *InputService1TestShapeInputService1TestCaseOperation1Output) { + + if opInputService1TestCaseOperation1 == nil { + opInputService1TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + HTTPMethod: "POST", + } + } + + if input == nil { + input = &InputService1TestShapeInputShape{} + } + + req = c.newRequest(opInputService1TestCaseOperation1, input, output) + output = &InputService1TestShapeInputService1TestCaseOperation1Output{} + req.Data = output + return +} + +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1(input *InputService1TestShapeInputShape) (output *InputService1TestShapeInputService1TestCaseOperation1Output, err error) { + req, out := c.InputService1TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opInputService1TestCaseOperation1 *aws.Operation + +type InputService1TestShapeInputService1TestCaseOperation1Output struct { + metadataInputService1TestShapeInputService1TestCaseOperation1Output `json:"-", xml:"-"` +} + +type metadataInputService1TestShapeInputService1TestCaseOperation1Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService1TestShapeInputShape struct { + Name *string `type:"string"` + + metadataInputService1TestShapeInputShape `json:"-", xml:"-"` +} + +type metadataInputService1TestShapeInputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// InputService2ProtocolTest is a client for InputService2ProtocolTest. +type InputService2ProtocolTest struct { + *aws.Service +} + +// New returns a new InputService2ProtocolTest client. +func NewInputService2ProtocolTest(config *aws.Config) *InputService2ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "inputservice2protocoltest", + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &InputService2ProtocolTest{service} +} + +// newRequest creates a new request for a InputService2ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService2ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// InputService2TestCaseOperation1Request generates a request for the InputService2TestCaseOperation1 operation. +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1Request(input *InputService2TestShapeInputShape) (req *aws.Request, output *InputService2TestShapeInputService2TestCaseOperation1Output) { + + if opInputService2TestCaseOperation1 == nil { + opInputService2TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService2TestShapeInputShape{} + } + + req = c.newRequest(opInputService2TestCaseOperation1, input, output) + output = &InputService2TestShapeInputService2TestCaseOperation1Output{} + req.Data = output + return +} + +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1(input *InputService2TestShapeInputShape) (output *InputService2TestShapeInputService2TestCaseOperation1Output, err error) { + req, out := c.InputService2TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opInputService2TestCaseOperation1 *aws.Operation + +type InputService2TestShapeInputService2TestCaseOperation1Output struct { + metadataInputService2TestShapeInputService2TestCaseOperation1Output `json:"-", xml:"-"` +} + +type metadataInputService2TestShapeInputService2TestCaseOperation1Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService2TestShapeInputShape struct { + TimeArg *time.Time `type:"timestamp" timestampFormat:"unix"` + + metadataInputService2TestShapeInputShape `json:"-", xml:"-"` +} + +type metadataInputService2TestShapeInputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// InputService3ProtocolTest is a client for InputService3ProtocolTest. +type InputService3ProtocolTest struct { + *aws.Service +} + +// New returns a new InputService3ProtocolTest client. +func NewInputService3ProtocolTest(config *aws.Config) *InputService3ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "inputservice3protocoltest", + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &InputService3ProtocolTest{service} +} + +// newRequest creates a new request for a InputService3ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService3ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// InputService3TestCaseOperation1Request generates a request for the InputService3TestCaseOperation1 operation. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1Request(input *InputService3TestShapeInputShape) (req *aws.Request, output *InputService3TestShapeInputService3TestCaseOperation1Output) { + + if opInputService3TestCaseOperation1 == nil { + opInputService3TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService3TestShapeInputShape{} + } + + req = c.newRequest(opInputService3TestCaseOperation1, input, output) + output = &InputService3TestShapeInputService3TestCaseOperation1Output{} + req.Data = output + return +} + +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1(input *InputService3TestShapeInputShape) (output *InputService3TestShapeInputService3TestCaseOperation1Output, err error) { + req, out := c.InputService3TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opInputService3TestCaseOperation1 *aws.Operation + +// InputService3TestCaseOperation2Request generates a request for the InputService3TestCaseOperation2 operation. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2Request(input *InputService3TestShapeInputShape) (req *aws.Request, output *InputService3TestShapeInputService3TestCaseOperation2Output) { + + if opInputService3TestCaseOperation2 == nil { + opInputService3TestCaseOperation2 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService3TestShapeInputShape{} + } + + req = c.newRequest(opInputService3TestCaseOperation2, input, output) + output = &InputService3TestShapeInputService3TestCaseOperation2Output{} + req.Data = output + return +} + +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2(input *InputService3TestShapeInputShape) (output *InputService3TestShapeInputService3TestCaseOperation2Output, err error) { + req, out := c.InputService3TestCaseOperation2Request(input) + output = out + err = req.Send() + return +} + +var opInputService3TestCaseOperation2 *aws.Operation + +type InputService3TestShapeInputService3TestCaseOperation1Output struct { + metadataInputService3TestShapeInputService3TestCaseOperation1Output `json:"-", xml:"-"` +} + +type metadataInputService3TestShapeInputService3TestCaseOperation1Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService3TestShapeInputService3TestCaseOperation2Output struct { + metadataInputService3TestShapeInputService3TestCaseOperation2Output `json:"-", xml:"-"` +} + +type metadataInputService3TestShapeInputService3TestCaseOperation2Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService3TestShapeInputShape struct { + BlobArg []byte `type:"blob"` + + BlobMap *map[string][]byte `type:"map"` + + metadataInputService3TestShapeInputShape `json:"-", xml:"-"` +} + +type metadataInputService3TestShapeInputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// InputService4ProtocolTest is a client for InputService4ProtocolTest. +type InputService4ProtocolTest struct { + *aws.Service +} + +// New returns a new InputService4ProtocolTest client. +func NewInputService4ProtocolTest(config *aws.Config) *InputService4ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "inputservice4protocoltest", + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &InputService4ProtocolTest{service} +} + +// newRequest creates a new request for a InputService4ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService4ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// InputService4TestCaseOperation1Request generates a request for the InputService4TestCaseOperation1 operation. +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1Request(input *InputService4TestShapeInputShape) (req *aws.Request, output *InputService4TestShapeInputService4TestCaseOperation1Output) { + + if opInputService4TestCaseOperation1 == nil { + opInputService4TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + HTTPMethod: "POST", + } + } + + if input == nil { + input = &InputService4TestShapeInputShape{} + } + + req = c.newRequest(opInputService4TestCaseOperation1, input, output) + output = &InputService4TestShapeInputService4TestCaseOperation1Output{} + req.Data = output + return +} + +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1(input *InputService4TestShapeInputShape) (output *InputService4TestShapeInputService4TestCaseOperation1Output, err error) { + req, out := c.InputService4TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opInputService4TestCaseOperation1 *aws.Operation + +type InputService4TestShapeInputService4TestCaseOperation1Output struct { + metadataInputService4TestShapeInputService4TestCaseOperation1Output `json:"-", xml:"-"` +} + +type metadataInputService4TestShapeInputService4TestCaseOperation1Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService4TestShapeInputShape struct { + ListParam [][]byte `type:"list"` + + metadataInputService4TestShapeInputShape `json:"-", xml:"-"` +} + +type metadataInputService4TestShapeInputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// InputService5ProtocolTest is a client for InputService5ProtocolTest. +type InputService5ProtocolTest struct { + *aws.Service +} + +// New returns a new InputService5ProtocolTest client. +func NewInputService5ProtocolTest(config *aws.Config) *InputService5ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "inputservice5protocoltest", + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &InputService5ProtocolTest{service} +} + +// newRequest creates a new request for a InputService5ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService5ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// InputService5TestCaseOperation1Request generates a request for the InputService5TestCaseOperation1 operation. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation1Output) { + + if opInputService5TestCaseOperation1 == nil { + opInputService5TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService5TestShapeInputShape{} + } + + req = c.newRequest(opInputService5TestCaseOperation1, input, output) + output = &InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation1Output{} + req.Data = output + return +} + +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1(input *InputService5TestShapeInputShape) (output *InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation1Output, err error) { + req, out := c.InputService5TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opInputService5TestCaseOperation1 *aws.Operation + +// InputService5TestCaseOperation2Request generates a request for the InputService5TestCaseOperation2 operation. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation2Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestCaseOperation2Output) { + + if opInputService5TestCaseOperation2 == nil { + opInputService5TestCaseOperation2 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService5TestShapeInputShape{} + } + + req = c.newRequest(opInputService5TestCaseOperation2, input, output) + output = &InputService5TestShapeInputService5TestCaseOperation2Output{} + req.Data = output + return +} + +func (c *InputService5ProtocolTest) InputService5TestCaseOperation2(input *InputService5TestShapeInputShape) (output *InputService5TestShapeInputService5TestCaseOperation2Output, err error) { + req, out := c.InputService5TestCaseOperation2Request(input) + output = out + err = req.Send() + return +} + +var opInputService5TestCaseOperation2 *aws.Operation + +// InputService5TestCaseOperation3Request generates a request for the InputService5TestCaseOperation3 operation. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation3Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestCaseOperation3Output) { + + if opInputService5TestCaseOperation3 == nil { + opInputService5TestCaseOperation3 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService5TestShapeInputShape{} + } + + req = c.newRequest(opInputService5TestCaseOperation3, input, output) + output = &InputService5TestShapeInputService5TestCaseOperation3Output{} + req.Data = output + return +} + +func (c *InputService5ProtocolTest) InputService5TestCaseOperation3(input *InputService5TestShapeInputShape) (output *InputService5TestShapeInputService5TestCaseOperation3Output, err error) { + req, out := c.InputService5TestCaseOperation3Request(input) + output = out + err = req.Send() + return +} + +var opInputService5TestCaseOperation3 *aws.Operation + +// InputService5TestCaseOperation4Request generates a request for the InputService5TestCaseOperation4 operation. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation4Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation4Output) { + + if opInputService5TestCaseOperation4 == nil { + opInputService5TestCaseOperation4 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService5TestShapeInputShape{} + } + + req = c.newRequest(opInputService5TestCaseOperation4, input, output) + output = &InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation4Output{} + req.Data = output + return +} + +func (c *InputService5ProtocolTest) InputService5TestCaseOperation4(input *InputService5TestShapeInputShape) (output *InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation4Output, err error) { + req, out := c.InputService5TestCaseOperation4Request(input) + output = out + err = req.Send() + return +} + +var opInputService5TestCaseOperation4 *aws.Operation + +// InputService5TestCaseOperation5Request generates a request for the InputService5TestCaseOperation5 operation. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation5Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation5Output) { + + if opInputService5TestCaseOperation5 == nil { + opInputService5TestCaseOperation5 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService5TestShapeInputShape{} + } + + req = c.newRequest(opInputService5TestCaseOperation5, input, output) + output = &InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation5Output{} + req.Data = output + return +} + +func (c *InputService5ProtocolTest) InputService5TestCaseOperation5(input *InputService5TestShapeInputShape) (output *InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation5Output, err error) { + req, out := c.InputService5TestCaseOperation5Request(input) + output = out + err = req.Send() + return +} + +var opInputService5TestCaseOperation5 *aws.Operation + +// InputService5TestCaseOperation6Request generates a request for the InputService5TestCaseOperation6 operation. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation6Request(input *InputService5TestShapeInputShape) (req *aws.Request, output *InputService5TestShapeInputService5TestCaseOperation6Output) { + + if opInputService5TestCaseOperation6 == nil { + opInputService5TestCaseOperation6 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &InputService5TestShapeInputShape{} + } + + req = c.newRequest(opInputService5TestCaseOperation6, input, output) + output = &InputService5TestShapeInputService5TestCaseOperation6Output{} + req.Data = output + return +} + +func (c *InputService5ProtocolTest) InputService5TestCaseOperation6(input *InputService5TestShapeInputShape) (output *InputService5TestShapeInputService5TestCaseOperation6Output, err error) { + req, out := c.InputService5TestCaseOperation6Request(input) + output = out + err = req.Send() + return +} + +var opInputService5TestCaseOperation6 *aws.Operation + +type InputService5TestShapeInputService5TestCaseOperation2Output struct { + metadataInputService5TestShapeInputService5TestCaseOperation2Output `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeInputService5TestCaseOperation2Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService5TestShapeInputService5TestCaseOperation3Output struct { + metadataInputService5TestShapeInputService5TestCaseOperation3Output `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeInputService5TestCaseOperation3Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService5TestShapeInputService5TestCaseOperation6Output struct { + metadataInputService5TestShapeInputService5TestCaseOperation6Output `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeInputService5TestCaseOperation6Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation1Output struct { + metadataInputService5TestShapeInputService5TestShapeInputService5TestCaseOperation1Output `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeInputService5TestShapeInputService5TestCaseOperation1Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation4Output struct { + metadataInputService5TestShapeInputService5TestShapeInputService5TestCaseOperation4Output `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeInputService5TestShapeInputService5TestCaseOperation4Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService5TestShapeInputService5TestShapeInputService5TestCaseOperation5Output struct { + metadataInputService5TestShapeInputService5TestShapeInputService5TestCaseOperation5Output `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeInputService5TestShapeInputService5TestCaseOperation5Output struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService5TestShapeInputShape struct { + RecursiveStruct *InputService5TestShapeRecursiveStructType `type:"structure"` + + metadataInputService5TestShapeInputShape `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeInputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +type InputService5TestShapeRecursiveStructType struct { + NoRecurse *string `type:"string"` + + RecursiveList []*InputService5TestShapeRecursiveStructType `type:"list"` + + RecursiveMap *map[string]*InputService5TestShapeRecursiveStructType `type:"map"` + + RecursiveStruct *InputService5TestShapeRecursiveStructType `type:"structure"` + + metadataInputService5TestShapeRecursiveStructType `json:"-", xml:"-"` +} + +type metadataInputService5TestShapeRecursiveStructType struct { + SDKShapeTraits bool `type:"structure"` +} + +// +// Tests begin here +// + +func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) { + svc := NewInputService1ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService1TestShapeInputShape{ + Name: aws.String("myname"), + } + req, _ := svc.InputService1TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"Name":"myname"}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService2ProtocolTestTimestampValuesCase1(t *testing.T) { + svc := NewInputService2ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService2TestShapeInputShape{ + TimeArg: aws.Time(time.Unix(1422172800, 0)), + } + req, _ := svc.InputService2TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"TimeArg":1422172800}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService3ProtocolTestBase64EncodedBlobsCase1(t *testing.T) { + svc := NewInputService3ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService3TestShapeInputShape{ + BlobArg: []byte("foo"), + } + req, _ := svc.InputService3TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"BlobArg":"Zm9v"}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService3ProtocolTestBase64EncodedBlobsCase2(t *testing.T) { + svc := NewInputService3ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService3TestShapeInputShape{ + BlobMap: &map[string][]byte{ + "key1": []byte("foo"), + "key2": []byte("bar"), + }, + } + req, _ := svc.InputService3TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"BlobMap":{"key1":"Zm9v","key2":"YmFy"}}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService4ProtocolTestNestedBlobsCase1(t *testing.T) { + svc := NewInputService4ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService4TestShapeInputShape{ + ListParam: [][]byte{ + []byte("foo"), + []byte("bar"), + }, + } + req, _ := svc.InputService4TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"ListParam":["Zm9v","YmFy"]}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService5ProtocolTestRecursiveShapesCase1(t *testing.T) { + svc := NewInputService5ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService5TestShapeInputShape{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + } + req, _ := svc.InputService5TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"RecursiveStruct":{"NoRecurse":"foo"}}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService5ProtocolTestRecursiveShapesCase2(t *testing.T) { + svc := NewInputService5ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService5TestShapeInputShape{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + }, + } + req, _ := svc.InputService5TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"RecursiveStruct":{"RecursiveStruct":{"NoRecurse":"foo"}}}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService5ProtocolTestRecursiveShapesCase3(t *testing.T) { + svc := NewInputService5ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService5TestShapeInputShape{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation3Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"RecursiveStruct":{"RecursiveStruct":{"RecursiveStruct":{"RecursiveStruct":{"NoRecurse":"foo"}}}}}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService5ProtocolTestRecursiveShapesCase4(t *testing.T) { + svc := NewInputService5ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService5TestShapeInputShape{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveList: []*InputService5TestShapeRecursiveStructType{ + &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("bar"), + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation4Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"RecursiveStruct":{"RecursiveList":[{"NoRecurse":"foo"},{"NoRecurse":"bar"}]}}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService5ProtocolTestRecursiveShapesCase5(t *testing.T) { + svc := NewInputService5ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService5TestShapeInputShape{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveList: []*InputService5TestShapeRecursiveStructType{ + &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("bar"), + }, + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation5Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"RecursiveStruct":{"RecursiveList":[{"NoRecurse":"foo"},{"RecursiveStruct":{"NoRecurse":"bar"}}]}}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + +func TestInputService5ProtocolTestRecursiveShapesCase6(t *testing.T) { + svc := NewInputService5ProtocolTest(nil) + svc.Endpoint = "https://test" + + input := &InputService5TestShapeInputShape{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveMap: &map[string]*InputService5TestShapeRecursiveStructType{ + "bar": &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("bar"), + }, + "foo": &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation6Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + assert.NoError(t, req.Error) + + // assert body + assert.NotNil(t, r.Body) + body, _ := ioutil.ReadAll(r.Body) + assert.Equal(t, util.Trim(`{"RecursiveStruct":{"RecursiveMap":{"bar":{"NoRecurse":"bar"},"foo":{"NoRecurse":"foo"}}}}`), util.Trim(string(body))) + + // assert URL + assert.Equal(t, "https://test/", r.URL.String()) + + // assert headers + assert.Equal(t, "application/x-amz-json-1.1", r.Header.Get("Content-Type")) + assert.Equal(t, "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target")) + +} + diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/jsonrpc.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/jsonrpc.go new file mode 100644 index 000000000..8d1151997 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/jsonrpc.go @@ -0,0 +1,88 @@ +package jsonrpc + +//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/json.json build_test.go +//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/json.json unmarshal_test.go + +import ( + "encoding/json" + "io/ioutil" + "strings" + + "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil" +) + +var emptyJSON = []byte("{}") + +func Build(req *aws.Request) { + var buf []byte + var err error + if req.ParamsFilled() { + buf, err = jsonutil.BuildJSON(req.Params) + if err != nil { + req.Error = err + return + } + } else { + buf = emptyJSON + } + + if req.Service.TargetPrefix != "" || string(buf) != "{}" { + req.SetBufferBody(buf) + } + + if req.Service.TargetPrefix != "" { + target := req.Service.TargetPrefix + "." + req.Operation.Name + req.HTTPRequest.Header.Add("X-Amz-Target", target) + } + if req.Service.JSONVersion != "" { + jsonVersion := req.Service.JSONVersion + req.HTTPRequest.Header.Add("Content-Type", "application/x-amz-json-"+jsonVersion) + } +} + +func Unmarshal(req *aws.Request) { + if req.DataFilled() { + err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body) + if err != nil { + req.Error = err + } + } + return +} + +func UnmarshalMeta(req *aws.Request) { + req.RequestID = req.HTTPResponse.Header.Get("x-amzn-requestid") +} + +func UnmarshalError(req *aws.Request) { + bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body) + if err != nil { + req.Error = err + return + } + if len(bodyBytes) == 0 { + req.Error = aws.APIError{ + StatusCode: req.HTTPResponse.StatusCode, + Message: req.HTTPResponse.Status, + } + return + } + var jsonErr jsonErrorResponse + if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { + req.Error = err + return + } + + codes := strings.SplitN(jsonErr.Code, "#", 2) + req.Error = aws.APIError{ + StatusCode: req.HTTPResponse.StatusCode, + Code: codes[len(codes)-1], + Message: jsonErr.Message, + } +} + +type jsonErrorResponse struct { + Code string `json:"__type"` + Message string `json:"message"` +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/unmarshal_test.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/unmarshal_test.go new file mode 100644 index 000000000..8f62472e8 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc/unmarshal_test.go @@ -0,0 +1,811 @@ +package jsonrpc_test + +import ( + "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/internal/protocol/jsonrpc" + "github.com/awslabs/aws-sdk-go/internal/signer/v4" + + "bytes" + "encoding/json" + "encoding/xml" + "github.com/awslabs/aws-sdk-go/internal/protocol/xml/xmlutil" + "github.com/awslabs/aws-sdk-go/internal/util" + "github.com/stretchr/testify/assert" + "io" + "io/ioutil" + "net/http" + "net/url" + "testing" + "time" +) + +var _ bytes.Buffer // always import bytes +var _ http.Request +var _ json.Marshaler +var _ time.Time +var _ xmlutil.XMLNode +var _ xml.Attr +var _ = ioutil.Discard +var _ = util.Trim("") +var _ = url.Values{} +var _ = io.EOF + +// OutputService1ProtocolTest is a client for OutputService1ProtocolTest. +type OutputService1ProtocolTest struct { + *aws.Service +} + +// New returns a new OutputService1ProtocolTest client. +func NewOutputService1ProtocolTest(config *aws.Config) *OutputService1ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "outputservice1protocoltest", + APIVersion: "", + JSONVersion: "", + TargetPrefix: "", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &OutputService1ProtocolTest{service} +} + +// newRequest creates a new request for a OutputService1ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService1ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// OutputService1TestCaseOperation1Request generates a request for the OutputService1TestCaseOperation1 operation. +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (req *aws.Request, output *OutputService1TestShapeOutputShape) { + + if opOutputService1TestCaseOperation1 == nil { + opOutputService1TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{} + } + + req = c.newRequest(opOutputService1TestCaseOperation1, input, output) + output = &OutputService1TestShapeOutputShape{} + req.Data = output + return +} + +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (output *OutputService1TestShapeOutputShape, err error) { + req, out := c.OutputService1TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opOutputService1TestCaseOperation1 *aws.Operation + +type OutputService1TestShapeOutputService1TestCaseOperation1Input struct { + metadataOutputService1TestShapeOutputService1TestCaseOperation1Input `json:"-", xml:"-"` +} + +type metadataOutputService1TestShapeOutputService1TestCaseOperation1Input struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService1TestShapeOutputShape struct { + metadataOutputService1TestShapeOutputShape `json:"-", xml:"-"` +} + +type metadataOutputService1TestShapeOutputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// OutputService2ProtocolTest is a client for OutputService2ProtocolTest. +type OutputService2ProtocolTest struct { + *aws.Service +} + +// New returns a new OutputService2ProtocolTest client. +func NewOutputService2ProtocolTest(config *aws.Config) *OutputService2ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "outputservice2protocoltest", + APIVersion: "", + JSONVersion: "", + TargetPrefix: "", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &OutputService2ProtocolTest{service} +} + +// newRequest creates a new request for a OutputService2ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService2ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// OutputService2TestCaseOperation1Request generates a request for the OutputService2TestCaseOperation1 operation. +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1Request(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (req *aws.Request, output *OutputService2TestShapeOutputShape) { + + if opOutputService2TestCaseOperation1 == nil { + opOutputService2TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &OutputService2TestShapeOutputService2TestCaseOperation1Input{} + } + + req = c.newRequest(opOutputService2TestCaseOperation1, input, output) + output = &OutputService2TestShapeOutputShape{} + req.Data = output + return +} + +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (output *OutputService2TestShapeOutputShape, err error) { + req, out := c.OutputService2TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opOutputService2TestCaseOperation1 *aws.Operation + +type OutputService2TestShapeOutputService2TestCaseOperation1Input struct { + metadataOutputService2TestShapeOutputService2TestCaseOperation1Input `json:"-", xml:"-"` +} + +type metadataOutputService2TestShapeOutputService2TestCaseOperation1Input struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService2TestShapeOutputShape struct { + Char *string `type:"character"` + + Double *float64 `type:"double"` + + FalseBool *bool `type:"boolean"` + + Float *float64 `type:"float"` + + Long *int64 `type:"long"` + + Num *int64 `type:"integer"` + + Str *string `type:"string"` + + TrueBool *bool `type:"boolean"` + + metadataOutputService2TestShapeOutputShape `json:"-", xml:"-"` +} + +type metadataOutputService2TestShapeOutputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// OutputService3ProtocolTest is a client for OutputService3ProtocolTest. +type OutputService3ProtocolTest struct { + *aws.Service +} + +// New returns a new OutputService3ProtocolTest client. +func NewOutputService3ProtocolTest(config *aws.Config) *OutputService3ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "outputservice3protocoltest", + APIVersion: "", + JSONVersion: "", + TargetPrefix: "", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &OutputService3ProtocolTest{service} +} + +// newRequest creates a new request for a OutputService3ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService3ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// OutputService3TestCaseOperation1Request generates a request for the OutputService3TestCaseOperation1 operation. +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1Request(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (req *aws.Request, output *OutputService3TestShapeOutputShape) { + + if opOutputService3TestCaseOperation1 == nil { + opOutputService3TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &OutputService3TestShapeOutputService3TestCaseOperation1Input{} + } + + req = c.newRequest(opOutputService3TestCaseOperation1, input, output) + output = &OutputService3TestShapeOutputShape{} + req.Data = output + return +} + +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (output *OutputService3TestShapeOutputShape, err error) { + req, out := c.OutputService3TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opOutputService3TestCaseOperation1 *aws.Operation + +type OutputService3TestShapeBlobContainer struct { + Foo []byte `locationName:"foo" type:"blob"` + + metadataOutputService3TestShapeBlobContainer `json:"-", xml:"-"` +} + +type metadataOutputService3TestShapeBlobContainer struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService3TestShapeOutputService3TestCaseOperation1Input struct { + metadataOutputService3TestShapeOutputService3TestCaseOperation1Input `json:"-", xml:"-"` +} + +type metadataOutputService3TestShapeOutputService3TestCaseOperation1Input struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService3TestShapeOutputShape struct { + BlobMember []byte `type:"blob"` + + StructMember *OutputService3TestShapeBlobContainer `type:"structure"` + + metadataOutputService3TestShapeOutputShape `json:"-", xml:"-"` +} + +type metadataOutputService3TestShapeOutputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// OutputService4ProtocolTest is a client for OutputService4ProtocolTest. +type OutputService4ProtocolTest struct { + *aws.Service +} + +// New returns a new OutputService4ProtocolTest client. +func NewOutputService4ProtocolTest(config *aws.Config) *OutputService4ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "outputservice4protocoltest", + APIVersion: "", + JSONVersion: "", + TargetPrefix: "", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &OutputService4ProtocolTest{service} +} + +// newRequest creates a new request for a OutputService4ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService4ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// OutputService4TestCaseOperation1Request generates a request for the OutputService4TestCaseOperation1 operation. +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1Request(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (req *aws.Request, output *OutputService4TestShapeOutputShape) { + + if opOutputService4TestCaseOperation1 == nil { + opOutputService4TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &OutputService4TestShapeOutputService4TestCaseOperation1Input{} + } + + req = c.newRequest(opOutputService4TestCaseOperation1, input, output) + output = &OutputService4TestShapeOutputShape{} + req.Data = output + return +} + +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (output *OutputService4TestShapeOutputShape, err error) { + req, out := c.OutputService4TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opOutputService4TestCaseOperation1 *aws.Operation + +type OutputService4TestShapeOutputService4TestCaseOperation1Input struct { + metadataOutputService4TestShapeOutputService4TestCaseOperation1Input `json:"-", xml:"-"` +} + +type metadataOutputService4TestShapeOutputService4TestCaseOperation1Input struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService4TestShapeOutputShape struct { + StructMember *OutputService4TestShapeTimeContainer `type:"structure"` + + TimeMember *time.Time `type:"timestamp" timestampFormat:"unix"` + + metadataOutputService4TestShapeOutputShape `json:"-", xml:"-"` +} + +type metadataOutputService4TestShapeOutputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService4TestShapeTimeContainer struct { + Foo *time.Time `locationName:"foo" type:"timestamp" timestampFormat:"unix"` + + metadataOutputService4TestShapeTimeContainer `json:"-", xml:"-"` +} + +type metadataOutputService4TestShapeTimeContainer struct { + SDKShapeTraits bool `type:"structure"` +} + +// OutputService5ProtocolTest is a client for OutputService5ProtocolTest. +type OutputService5ProtocolTest struct { + *aws.Service +} + +// New returns a new OutputService5ProtocolTest client. +func NewOutputService5ProtocolTest(config *aws.Config) *OutputService5ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "outputservice5protocoltest", + APIVersion: "", + JSONVersion: "", + TargetPrefix: "", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &OutputService5ProtocolTest{service} +} + +// newRequest creates a new request for a OutputService5ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService5ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// OutputService5TestCaseOperation1Request generates a request for the OutputService5TestCaseOperation1 operation. +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1Request(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (req *aws.Request, output *OutputService5TestShapeOutputShape) { + + if opOutputService5TestCaseOperation1 == nil { + opOutputService5TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &OutputService5TestShapeOutputService5TestCaseOperation1Input{} + } + + req = c.newRequest(opOutputService5TestCaseOperation1, input, output) + output = &OutputService5TestShapeOutputShape{} + req.Data = output + return +} + +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (output *OutputService5TestShapeOutputShape, err error) { + req, out := c.OutputService5TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opOutputService5TestCaseOperation1 *aws.Operation + +type OutputService5TestShapeOutputService5TestCaseOperation1Input struct { + metadataOutputService5TestShapeOutputService5TestCaseOperation1Input `json:"-", xml:"-"` +} + +type metadataOutputService5TestShapeOutputService5TestCaseOperation1Input struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService5TestShapeOutputShape struct { + ListMember []*string `type:"list"` + + metadataOutputService5TestShapeOutputShape `json:"-", xml:"-"` +} + +type metadataOutputService5TestShapeOutputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// OutputService6ProtocolTest is a client for OutputService6ProtocolTest. +type OutputService6ProtocolTest struct { + *aws.Service +} + +// New returns a new OutputService6ProtocolTest client. +func NewOutputService6ProtocolTest(config *aws.Config) *OutputService6ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "outputservice6protocoltest", + APIVersion: "", + JSONVersion: "", + TargetPrefix: "", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &OutputService6ProtocolTest{service} +} + +// newRequest creates a new request for a OutputService6ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService6ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// OutputService6TestCaseOperation1Request generates a request for the OutputService6TestCaseOperation1 operation. +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1Request(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (req *aws.Request, output *OutputService6TestShapeOutputShape) { + + if opOutputService6TestCaseOperation1 == nil { + opOutputService6TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &OutputService6TestShapeOutputService6TestCaseOperation1Input{} + } + + req = c.newRequest(opOutputService6TestCaseOperation1, input, output) + output = &OutputService6TestShapeOutputShape{} + req.Data = output + return +} + +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (output *OutputService6TestShapeOutputShape, err error) { + req, out := c.OutputService6TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opOutputService6TestCaseOperation1 *aws.Operation + +type OutputService6TestShapeOutputService6TestCaseOperation1Input struct { + metadataOutputService6TestShapeOutputService6TestCaseOperation1Input `json:"-", xml:"-"` +} + +type metadataOutputService6TestShapeOutputService6TestCaseOperation1Input struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService6TestShapeOutputShape struct { + MapMember *map[string][]*int64 `type:"map"` + + metadataOutputService6TestShapeOutputShape `json:"-", xml:"-"` +} + +type metadataOutputService6TestShapeOutputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// OutputService7ProtocolTest is a client for OutputService7ProtocolTest. +type OutputService7ProtocolTest struct { + *aws.Service +} + +// New returns a new OutputService7ProtocolTest client. +func NewOutputService7ProtocolTest(config *aws.Config) *OutputService7ProtocolTest { + if config == nil { + config = &aws.Config{} + } + + service := &aws.Service{ + Config: aws.DefaultConfig.Merge(config), + ServiceName: "outputservice7protocoltest", + APIVersion: "", + JSONVersion: "", + TargetPrefix: "", + } + service.Initialize() + + // Handlers + service.Handlers.Sign.PushBack(v4.Sign) + service.Handlers.Build.PushBack(jsonrpc.Build) + service.Handlers.Unmarshal.PushBack(jsonrpc.Unmarshal) + service.Handlers.UnmarshalMeta.PushBack(jsonrpc.UnmarshalMeta) + service.Handlers.UnmarshalError.PushBack(jsonrpc.UnmarshalError) + + return &OutputService7ProtocolTest{service} +} + +// newRequest creates a new request for a OutputService7ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService7ProtocolTest) newRequest(op *aws.Operation, params, data interface{}) *aws.Request { + req := aws.NewRequest(c.Service, op, params, data) + + return req +} + +// OutputService7TestCaseOperation1Request generates a request for the OutputService7TestCaseOperation1 operation. +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1Request(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (req *aws.Request, output *OutputService7TestShapeOutputShape) { + + if opOutputService7TestCaseOperation1 == nil { + opOutputService7TestCaseOperation1 = &aws.Operation{ + Name: "OperationName", + } + } + + if input == nil { + input = &OutputService7TestShapeOutputService7TestCaseOperation1Input{} + } + + req = c.newRequest(opOutputService7TestCaseOperation1, input, output) + output = &OutputService7TestShapeOutputShape{} + req.Data = output + return +} + +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (output *OutputService7TestShapeOutputShape, err error) { + req, out := c.OutputService7TestCaseOperation1Request(input) + output = out + err = req.Send() + return +} + +var opOutputService7TestCaseOperation1 *aws.Operation + +type OutputService7TestShapeOutputService7TestCaseOperation1Input struct { + metadataOutputService7TestShapeOutputService7TestCaseOperation1Input `json:"-", xml:"-"` +} + +type metadataOutputService7TestShapeOutputService7TestCaseOperation1Input struct { + SDKShapeTraits bool `type:"structure"` +} + +type OutputService7TestShapeOutputShape struct { + StrType *string `type:"string"` + + metadataOutputService7TestShapeOutputShape `json:"-", xml:"-"` +} + +type metadataOutputService7TestShapeOutputShape struct { + SDKShapeTraits bool `type:"structure"` +} + +// +// Tests begin here +// + +func TestOutputService1ProtocolTestEmptyBodyCase1(t *testing.T) { + svc := NewOutputService1ProtocolTest(nil) + + buf := bytes.NewReader([]byte("")) + req, out := svc.OutputService1TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + assert.NoError(t, req.Error) + + // assert response + assert.NotNil(t, out) // ensure out variable is used + +} + +func TestOutputService2ProtocolTestScalarMembersCase1(t *testing.T) { + svc := NewOutputService2ProtocolTest(nil) + + buf := bytes.NewReader([]byte("{\"Str\": \"myname\", \"Num\": 123, \"FalseBool\": false, \"TrueBool\": true, \"Float\": 1.2, \"Double\": 1.3, \"Long\": 200, \"Char\": \"a\"}")) + req, out := svc.OutputService2TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + assert.NoError(t, req.Error) + + // assert response + assert.NotNil(t, out) // ensure out variable is used + assert.Equal(t, "a", *out.Char) + assert.Equal(t, 1.3, *out.Double) + assert.Equal(t, false, *out.FalseBool) + assert.Equal(t, 1.2, *out.Float) + assert.Equal(t, int64(200), *out.Long) + assert.Equal(t, int64(123), *out.Num) + assert.Equal(t, "myname", *out.Str) + assert.Equal(t, true, *out.TrueBool) + +} + +func TestOutputService3ProtocolTestBlobMembersCase1(t *testing.T) { + svc := NewOutputService3ProtocolTest(nil) + + buf := bytes.NewReader([]byte("{\"BlobMember\": \"aGkh\", \"StructMember\": {\"foo\": \"dGhlcmUh\"}}")) + req, out := svc.OutputService3TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + assert.NoError(t, req.Error) + + // assert response + assert.NotNil(t, out) // ensure out variable is used + assert.Equal(t, "hi!", string(out.BlobMember)) + assert.Equal(t, "there!", string(out.StructMember.Foo)) + +} + +func TestOutputService4ProtocolTestTimestampMembersCase1(t *testing.T) { + svc := NewOutputService4ProtocolTest(nil) + + buf := bytes.NewReader([]byte("{\"TimeMember\": 1398796238, \"StructMember\": {\"foo\": 1398796238}}")) + req, out := svc.OutputService4TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + assert.NoError(t, req.Error) + + // assert response + assert.NotNil(t, out) // ensure out variable is used + assert.Equal(t, time.Unix(1.398796238e+09, 0).UTC().String(), out.StructMember.Foo.String()) + assert.Equal(t, time.Unix(1.398796238e+09, 0).UTC().String(), out.TimeMember.String()) + +} + +func TestOutputService5ProtocolTestListsCase1(t *testing.T) { + svc := NewOutputService5ProtocolTest(nil) + + buf := bytes.NewReader([]byte("{\"ListMember\": [\"a\", \"b\"]}")) + req, out := svc.OutputService5TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + assert.NoError(t, req.Error) + + // assert response + assert.NotNil(t, out) // ensure out variable is used + assert.Equal(t, "a", *out.ListMember[0]) + assert.Equal(t, "b", *out.ListMember[1]) + +} + +func TestOutputService6ProtocolTestMapsCase1(t *testing.T) { + svc := NewOutputService6ProtocolTest(nil) + + buf := bytes.NewReader([]byte("{\"MapMember\": {\"a\": [1, 2], \"b\": [3, 4]}}")) + req, out := svc.OutputService6TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + assert.NoError(t, req.Error) + + // assert response + assert.NotNil(t, out) // ensure out variable is used + assert.Equal(t, int64(1), *(*out.MapMember)["a"][0]) + assert.Equal(t, int64(2), *(*out.MapMember)["a"][1]) + assert.Equal(t, int64(3), *(*out.MapMember)["b"][0]) + assert.Equal(t, int64(4), *(*out.MapMember)["b"][1]) + +} + +func TestOutputService7ProtocolTestIgnoresExtraDataCase1(t *testing.T) { + svc := NewOutputService7ProtocolTest(nil) + + buf := bytes.NewReader([]byte("{\"foo\": \"bar\"}")) + req, out := svc.OutputService7TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + assert.NoError(t, req.Error) + + // assert response + assert.NotNil(t, out) // ensure out variable is used + +} + diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4.go new file mode 100644 index 000000000..0a2640545 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4.go @@ -0,0 +1,301 @@ +package v4 + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "time" + + "github.com/awslabs/aws-sdk-go/aws" +) + +const ( + authHeaderPrefix = "AWS4-HMAC-SHA256" + timeFormat = "20060102T150405Z" + shortTimeFormat = "20060102" +) + +var ignoredHeaders = map[string]bool{ + "Authorization": true, + "Content-Type": true, + "Content-Length": true, + "User-Agent": true, +} + +type signer struct { + Request *http.Request + Time time.Time + ExpireTime time.Duration + ServiceName string + Region string + AccessKeyID string + SecretAccessKey string + SessionToken string + Query url.Values + Body io.ReadSeeker + Debug uint + Logger io.Writer + + isPresign bool + formattedTime string + formattedShortTime string + + signedHeaders string + canonicalHeaders string + canonicalString string + credentialString string + stringToSign string + signature string + authorization string +} + +// Sign requests with signature version 4. +func Sign(req *aws.Request) { + creds, err := req.Service.Config.Credentials.Credentials() + if err != nil { + req.Error = err + return + } + + region := req.Service.SigningRegion + if region == "" { + region = req.Service.Config.Region + } + + s := signer{ + Request: req.HTTPRequest, + Time: req.Time, + ExpireTime: req.ExpireTime, + Query: req.HTTPRequest.URL.Query(), + Body: req.Body, + ServiceName: req.Service.ServiceName, + Region: region, + AccessKeyID: creds.AccessKeyID, + SecretAccessKey: creds.SecretAccessKey, + SessionToken: creds.SessionToken, + Debug: req.Service.Config.LogLevel, + Logger: req.Service.Config.Logger, + } + s.sign() + return +} + +func (v4 *signer) sign() { + if v4.ExpireTime != 0 { + v4.isPresign = true + } + + if v4.isPresign { + v4.Query.Set("X-Amz-Algorithm", authHeaderPrefix) + if v4.SessionToken != "" { + v4.Query.Set("X-Amz-Security-Token", v4.SessionToken) + } else { + v4.Query.Del("X-Amz-Security-Token") + } + } else if v4.SessionToken != "" { + v4.Request.Header.Set("X-Amz-Security-Token", v4.SessionToken) + } + + v4.build() + + if v4.Debug > 0 { + out := v4.Logger + fmt.Fprintf(out, "---[ CANONICAL STRING ]-----------------------------\n") + fmt.Fprintln(out, v4.canonicalString) + fmt.Fprintf(out, "---[ STRING TO SIGN ]--------------------------------\n") + fmt.Fprintln(out, v4.stringToSign) + fmt.Fprintf(out, "---[ SIGNED URL ]--------------------------------\n") + fmt.Fprintln(out, v4.Request.URL) + fmt.Fprintf(out, "-----------------------------------------------------\n") + } +} + +func (v4 *signer) build() { + v4.buildTime() // no depends + v4.buildCredentialString() // no depends + if v4.isPresign { + v4.buildQuery() // no depends + } + v4.buildCanonicalHeaders() // depends on cred string + v4.buildCanonicalString() // depends on canon headers / signed headers + v4.buildStringToSign() // depends on canon string + v4.buildSignature() // depends on string to sign + + if v4.isPresign { + v4.Request.URL.RawQuery += "&X-Amz-Signature=" + v4.signature + } else { + parts := []string{ + authHeaderPrefix + " Credential=" + v4.AccessKeyID + "/" + v4.credentialString, + "SignedHeaders=" + v4.signedHeaders, + "Signature=" + v4.signature, + } + v4.Request.Header.Set("Authorization", strings.Join(parts, ", ")) + } +} + +func (v4 *signer) buildTime() { + v4.formattedTime = v4.Time.UTC().Format(timeFormat) + v4.formattedShortTime = v4.Time.UTC().Format(shortTimeFormat) + + if v4.isPresign { + duration := int64(v4.ExpireTime / time.Second) + v4.Query.Set("X-Amz-Date", v4.formattedTime) + v4.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10)) + } else { + v4.Request.Header.Set("X-Amz-Date", v4.formattedTime) + } +} + +func (v4 *signer) buildCredentialString() { + v4.credentialString = strings.Join([]string{ + v4.formattedShortTime, + v4.Region, + v4.ServiceName, + "aws4_request", + }, "/") + + if v4.isPresign { + v4.Query.Set("X-Amz-Credential", v4.AccessKeyID+"/"+v4.credentialString) + } +} + +func (v4 *signer) buildQuery() { + for k, h := range v4.Request.Header { + if strings.HasPrefix(http.CanonicalHeaderKey(k), "X-Amz-") { + continue // never hoist x-amz-* headers, they must be signed + } + if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok { + continue // never hoist ignored headers + } + + v4.Request.Header.Del(k) + v4.Query.Del(k) + for _, v := range h { + v4.Query.Add(k, v) + } + } +} + +func (v4 *signer) buildCanonicalHeaders() { + headers := make([]string, 0) + headers = append(headers, "host") + for k, _ := range v4.Request.Header { + if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok { + continue // ignored header + } + headers = append(headers, strings.ToLower(k)) + } + sort.Strings(headers) + + v4.signedHeaders = strings.Join(headers, ";") + + if v4.isPresign { + v4.Query.Set("X-Amz-SignedHeaders", v4.signedHeaders) + } + + headerValues := make([]string, len(headers)) + for i, k := range headers { + if k == "host" { + headerValues[i] = "host:" + v4.Request.URL.Host + } else { + headerValues[i] = k + ":" + + strings.Join(v4.Request.Header[http.CanonicalHeaderKey(k)], ",") + } + } + + v4.canonicalHeaders = strings.Join(headerValues, "\n") +} + +func (v4 *signer) buildCanonicalString() { + v4.Request.URL.RawQuery = v4.Query.Encode() + uri := v4.Request.URL.Opaque + if uri != "" { + uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/") + } else { + uri = v4.Request.URL.Path + } + if uri == "" { + uri = "/" + } + + v4.canonicalString = strings.Join([]string{ + v4.Request.Method, + uri, + v4.Request.URL.RawQuery, + v4.canonicalHeaders + "\n", + v4.signedHeaders, + v4.bodyDigest(), + }, "\n") +} + +func (v4 *signer) buildStringToSign() { + v4.stringToSign = strings.Join([]string{ + authHeaderPrefix, + v4.formattedTime, + v4.credentialString, + hex.EncodeToString(makeSha256([]byte(v4.canonicalString))), + }, "\n") +} + +func (v4 *signer) buildSignature() { + secret := v4.SecretAccessKey + date := makeHmac([]byte("AWS4"+secret), []byte(v4.formattedShortTime)) + region := makeHmac(date, []byte(v4.Region)) + service := makeHmac(region, []byte(v4.ServiceName)) + credentials := makeHmac(service, []byte("aws4_request")) + signature := makeHmac(credentials, []byte(v4.stringToSign)) + v4.signature = hex.EncodeToString(signature) +} + +func (v4 *signer) bodyDigest() string { + hash := v4.Request.Header.Get("X-Amz-Content-Sha256") + if hash == "" { + if v4.isPresign && v4.ServiceName == "s3" { + hash = "UNSIGNED-PAYLOAD" + } else if v4.Body == nil { + hash = hex.EncodeToString(makeSha256([]byte{})) + } else { + hash = hex.EncodeToString(makeSha256Reader(v4.Body)) + } + v4.Request.Header.Add("X-Amz-Content-Sha256", hash) + } + return hash +} + +func makeHmac(key []byte, data []byte) []byte { + hash := hmac.New(sha256.New, key) + hash.Write(data) + return hash.Sum(nil) +} + +func makeSha256(data []byte) []byte { + hash := sha256.New() + hash.Write(data) + return hash.Sum(nil) +} + +func makeSha256Reader(reader io.ReadSeeker) []byte { + packet := make([]byte, 4096) + hash := sha256.New() + + reader.Seek(0, 0) + for { + n, err := reader.Read(packet) + if n > 0 { + hash.Write(packet[0:n]) + } + if err == io.EOF || n == 0 { + break + } + } + reader.Seek(0, 0) + + return hash.Sum(nil) +} diff --git a/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4_test.go b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4_test.go new file mode 100644 index 000000000..fb15c3949 --- /dev/null +++ b/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/internal/signer/v4/v4_test.go @@ -0,0 +1,89 @@ +package v4 + +import ( + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func buildSigner(serviceName string, region string, signTime time.Time, expireTime time.Duration, body string) signer { + endpoint := "https://" + serviceName + "." + region + ".amazonaws.com" + reader := strings.NewReader(body) + req, _ := http.NewRequest("POST", endpoint, reader) + req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()" + req.Header.Add("X-Amz-Target", "prefix.Operation") + req.Header.Add("Content-Type", "application/x-amz-json-1.0") + req.Header.Add("Content-Length", string(len(body))) + req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* ()") + + return signer{ + Request: req, + Time: signTime, + ExpireTime: expireTime, + Query: req.URL.Query(), + Body: reader, + ServiceName: serviceName, + Region: region, + AccessKeyID: "AKID", + SecretAccessKey: "SECRET", + SessionToken: "SESSION", + } +} + +func removeWS(text string) string { + text = strings.Replace(text, " ", "", -1) + text = strings.Replace(text, "\n", "", -1) + text = strings.Replace(text, "\t", "", -1) + return text +} + +func assertEqual(t *testing.T, expected, given string) { + if removeWS(expected) != removeWS(given) { + t.Errorf("\nExpected: %s\nGiven: %s", expected, given) + } +} + +func TestPresignRequest(t *testing.T) { + signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 300*time.Second, "{}") + signer.sign() + + expectedDate := "19700101T000000Z" + expectedHeaders := "host;x-amz-meta-other-header;x-amz-target" + expectedSig := "41c18d68f9191079dfeead4e3f034328f89d86c79f8e9d51dd48bb70eaf623fc" + expectedCred := "AKID/19700101/us-east-1/dynamodb/aws4_request" + + q := signer.Request.URL.Query() + assert.Equal(t, expectedSig, q.Get("X-Amz-Signature")) + assert.Equal(t, expectedCred, q.Get("X-Amz-Credential")) + assert.Equal(t, expectedHeaders, q.Get("X-Amz-SignedHeaders")) + assert.Equal(t, expectedDate, q.Get("X-Amz-Date")) +} + +func TestSignRequest(t *testing.T) { + signer := buildSigner("dynamodb", "us-east-1", time.Unix(0, 0), 0, "{}") + signer.sign() + + expectedDate := "19700101T000000Z" + expectedSig := "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/dynamodb/aws4_request, SignedHeaders=host;x-amz-date;x-amz-meta-other-header;x-amz-security-token;x-amz-target, Signature=0196959cabd964bd10c05217b40ed151882dd394190438bab0c658dafdbff7a1" + + q := signer.Request.Header + assert.Equal(t, expectedSig, q.Get("Authorization")) + assert.Equal(t, expectedDate, q.Get("X-Amz-Date")) +} + +func BenchmarkPresignRequest(b *testing.B) { + signer := buildSigner("dynamodb", "us-east-1", time.Now(), 300*time.Second, "{}") + for i := 0; i < b.N; i++ { + signer.sign() + } +} + +func BenchmarkSignRequest(b *testing.B) { + signer := buildSigner("dynamodb", "us-east-1", time.Now(), 0, "{}") + for i := 0; i < b.N; i++ { + signer.sign() + } +}