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, } }
func UnmarshalError(r *aws.Request) { code := r.HTTPResponse.Header.Get("X-Amzn-Errortype") bodyBytes, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = err return } if len(bodyBytes) == 0 { r.Error = aws.APIError{ StatusCode: r.HTTPResponse.StatusCode, Message: r.HTTPResponse.Status, } return } var jsonErr jsonErrorResponse if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { r.Error = err return } codes := strings.SplitN(code, ":", 2) r.Error = aws.APIError{ StatusCode: r.HTTPResponse.StatusCode, Code: codes[0], Message: jsonErr.Message, } }
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 unmarshalError(r *aws.Request) { defer r.HTTPResponse.Body.Close() if r.HTTPResponse.ContentLength == int64(0) { // No body, use status code to generate an APIError r.Error = aws.APIError{ StatusCode: r.HTTPResponse.StatusCode, Code: strings.Replace(r.HTTPResponse.Status, " ", "", -1), Message: r.HTTPResponse.Status, } return } resp := &xmlErrorResponse{} err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) if err != nil && err != io.EOF { r.Error = err } else { r.Error = aws.APIError{ StatusCode: r.HTTPResponse.StatusCode, Code: resp.Code, Message: resp.Message, } } }
func Unmarshal(r *aws.Request) { if r.DataFilled() { v := reflect.Indirect(reflect.ValueOf(r.Data)) unmarshalBody(r, v) unmarshalLocationElements(r, v) } }
func Build(r *aws.Request) { if r.ParamsFilled() { v := reflect.ValueOf(r.Params).Elem() buildLocationElements(r, v) buildBody(r, v) } }
func setChecksumError(r *aws.Request, format string, args ...interface{}) { r.Retryable = true r.Error = &aws.APIError{ StatusCode: r.HTTPResponse.StatusCode, Code: "InvalidChecksum", Message: fmt.Sprintf(format, args...), } }
func Unmarshal(req *aws.Request) { if req.DataFilled() { err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body) if err != nil { req.Error = err } } return }
func assertMD5(t *testing.T, req *aws.Request) { err := req.Build() assert.NoError(t, err) b, _ := ioutil.ReadAll(req.HTTPRequest.Body) out := md5.Sum(b) assert.NotEmpty(t, b) assert.Equal(t, base64.StdEncoding.EncodeToString(out[:]), req.HTTPRequest.Header.Get("Content-MD5")) }
func addAccountID(r *aws.Request) { if !r.ParamsFilled() { return } v := reflect.Indirect(reflect.ValueOf(r.Params)) if f := v.FieldByName("AccountID"); f.Elem().String() == "" { f.Set(reflect.ValueOf(&defaultAccountID)) } }
func verifySendMessage(r *aws.Request) { if r.DataFilled() && r.ParamsFilled() { in := r.Params.(*SendMessageInput) out := r.Data.(*SendMessageOutput) err := checksumsMatch(in.MessageBody, out.MD5OfMessageBody) if err != nil { setChecksumError(r, err.Error()) } } }
func Unmarshal(r *aws.Request) { defer r.HTTPResponse.Body.Close() if r.DataFilled() { decoder := xml.NewDecoder(r.HTTPResponse.Body) err := xmlutil.UnmarshalXML(r.Data, decoder, r.Operation.Name+"Result") if err != nil { r.Error = err return } } }
func populateLocationConstraint(r *aws.Request) { if r.ParamsFilled() && r.Config.Region != "us-east-1" { in := r.Params.(*CreateBucketInput) if in.CreateBucketConfiguration == nil { r.Params = awsutil.CopyOf(r.Params) in = r.Params.(*CreateBucketInput) in.CreateBucketConfiguration = &CreateBucketConfiguration{ LocationConstraint: &r.Config.Region, } } } }
func Build(r *aws.Request) { rest.Build(r) if t := rest.PayloadType(r.Params); t == "structure" || t == "" { var buf bytes.Buffer err := xmlutil.BuildXML(r.Params, xml.NewEncoder(&buf)) if err != nil { r.Error = err return } r.SetBufferBody(buf.Bytes()) } }
func verifyReceiveMessage(r *aws.Request) { if r.DataFilled() && r.ParamsFilled() { ids := []string{} out := r.Data.(*ReceiveMessageOutput) for _, msg := range out.Messages { err := checksumsMatch(msg.Body, msg.MD5OfBody) if err != nil { ids = append(ids, *msg.MessageID) } } if len(ids) > 0 { setChecksumError(r, "invalid messages: %s", strings.Join(ids, ", ")) } } }
func UnmarshalError(r *aws.Request) { defer r.HTTPResponse.Body.Close() resp := &xmlErrorResponse{} err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) if err != nil && err != io.EOF { r.Error = err } else { r.Error = aws.APIError{ StatusCode: r.HTTPResponse.StatusCode, Code: resp.Code, Message: resp.Message, } } }
func buildGetBucketLocation(r *aws.Request) { if r.DataFilled() { out := r.Data.(*GetBucketLocationOutput) b, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = err return } match := reBucketLocation.FindSubmatch(b) if len(match) > 1 { loc := string(match[1]) out.LocationConstraint = &loc } } }
// 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 buildHeader(r *aws.Request, v reflect.Value, name string) { str, err := convertType(v) if err != nil { r.Error = err } else if str != nil { r.HTTPRequest.Header.Add(name, *str) } }
func validateSSERequiresSSL(r *aws.Request) { if r.HTTPRequest.URL.Scheme != "https" { p := awsutil.ValuesAtPath(r.Params, "SSECustomerKey||CopySourceSSECustomerKey") if len(p) > 0 { r.Error = errSSERequiresSSL } } }
func buildQueryString(r *aws.Request, v reflect.Value, name string, query url.Values) { str, err := convertType(v) if err != nil { r.Error = err } else if str != nil { query.Set(name, *str) } }
func Build(r *aws.Request) { body := url.Values{ "Action": {r.Operation.Name}, "Version": {r.Service.APIVersion}, } if err := queryutil.Parse(body, r.Params, false); err != nil { r.Error = err return } if r.ExpireTime == 0 { r.HTTPRequest.Method = "POST" r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") r.SetBufferBody([]byte(body.Encode())) } else { // This is a pre-signed request r.HTTPRequest.Method = "GET" r.HTTPRequest.URL.RawQuery = body.Encode() } }
func Unmarshal(r *aws.Request) { if t := rest.PayloadType(r.Data); t == "structure" || t == "" { defer r.HTTPResponse.Body.Close() decoder := xml.NewDecoder(r.HTTPResponse.Body) err := xmlutil.UnmarshalXML(r.Data, decoder, "") if err != nil { r.Error = err return } } }
func buildURI(r *aws.Request, v reflect.Value, name string) { value, err := convertType(v) if err != nil { r.Error = err } else if value != nil { uri := r.HTTPRequest.URL.Path uri = strings.Replace(uri, "{"+name+"}", escapePath(*value, true), -1) uri = strings.Replace(uri, "{"+name+"+}", escapePath(*value, false), -1) r.HTTPRequest.URL.Path = uri } }
func buildHeaderMap(r *aws.Request, v reflect.Value, prefix string) { for _, key := range v.MapKeys() { str, err := convertType(v.MapIndex(key)) if err != nil { r.Error = err } else if str != nil { r.HTTPRequest.Header.Add(prefix+key.String(), *str) } } }
func validateCRC32(r *aws.Request) { if r.Error != nil { return // already have an error, no need to verify CRC } // Checksum validation is off, skip if r.Service.Config.DisableComputeChecksums { return } // Try to get CRC from response header := r.HTTPResponse.Header.Get("X-Amz-Crc32") if header == "" { return // No header, skip } expected, err := strconv.ParseUint(header, 10, 32) if err != nil { return // Could not determine CRC value, skip } buf, err := drainBody(r.HTTPResponse.Body) if err != nil { // failed to read the response body, skip return } // Reset body for subsequent reads r.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(buf.Bytes())) // Compute the CRC checksum crc := crc32.ChecksumIEEE(buf.Bytes()) if crc != uint32(expected) { // CRC does not match, set a retryable error r.Retryable = true r.Error = &aws.APIError{ Code: "CRC32CheckFailed", Message: "CRC32 integrity check failed", } } }
func fillPresignedURL(r *aws.Request) { if !r.ParamsFilled() { return } params := r.Params.(*CopySnapshotInput) // Stop if PresignedURL/DestinationRegion is set if params.PresignedURL != nil || params.DestinationRegion != nil { return } // First generate a copy of parameters r.Params = awsutil.CopyOf(r.Params) params = r.Params.(*CopySnapshotInput) // Set destination region. Avoids infinite handler loop. // Also needed to sign sub-request. params.DestinationRegion = &r.Service.Config.Region // Create a new client pointing at source region. // We will use this to presign the CopySnapshot request against // the source region var config aws.Config awsutil.Copy(&config, r.Service.Config) config.Endpoint = "" config.Region = *params.SourceRegion client := New(&config) // Presign a CopySnapshot request with modified params req, _ := client.CopySnapshotRequest(params) url, err := req.Presign(300 * time.Second) // 5 minutes should be enough. if err != nil { // bubble error back up to original request r.Error = err } // We have our URL, set it on params params.PresignedURL = &url }
// contentMD5 computes and sets the HTTP Content-MD5 header for requests that // require it. func contentMD5(r *aws.Request) { h := md5.New() // hash the body. seek back to the first position after reading to reset // the body for transmission. copy errors may be assumed to be from the // body. _, err := io.Copy(h, r.Body) if err != nil { r.Error = fmt.Errorf("content-md5: read: %v", err) return } _, err = r.Body.Seek(0, 0) if err != nil { r.Error = fmt.Errorf("content-md5: seek: %v", err) return } // encode the md5 checksum in base64 and set the request header. sum := h.Sum(nil) sum64 := make([]byte, base64.StdEncoding.EncodedLen(len(sum))) base64.StdEncoding.Encode(sum64, sum) r.HTTPRequest.Header.Set("Content-MD5", string(sum64)) }
func unmarshalBody(r *aws.Request, v reflect.Value) { if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { if payloadName := field.Tag.Get("payload"); payloadName != "" { pfield, _ := v.Type().FieldByName(payloadName) if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { payload := reflect.Indirect(v.FieldByName(payloadName)) if payload.IsValid() { switch payload.Interface().(type) { case []byte: b, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = err } else { payload.Set(reflect.ValueOf(b)) } case string: b, err := ioutil.ReadAll(r.HTTPResponse.Body) if err != nil { r.Error = err } else { payload.Set(reflect.ValueOf(string(b))) } default: switch payload.Type().String() { case "io.ReadSeeker": payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body))) case "aws.ReadSeekCloser", "io.ReadCloser": payload.Set(reflect.ValueOf(r.HTTPResponse.Body)) default: r.Error = fmt.Errorf("unknown payload type %s", payload.Type()) } } } } } } }
func unmarshalLocationElements(r *aws.Request, v reflect.Value) { for i := 0; i < v.NumField(); i++ { m, field := v.Field(i), v.Type().Field(i) if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) { continue } if m.IsValid() { name := field.Tag.Get("locationName") if name == "" { name = field.Name } switch field.Tag.Get("location") { case "statusCode": unmarshalStatusCode(m, r.HTTPResponse.StatusCode) case "header": err := unmarshalHeader(m, r.HTTPResponse.Header.Get(name)) if err != nil { r.Error = err break } case "headers": prefix := field.Tag.Get("locationName") err := unmarshalHeaderMap(m, r.HTTPResponse.Header, prefix) if err != nil { r.Error = err break } } } if r.Error != nil { return } } }