// Initialize initializes the service. func (s *Service) Initialize() { if s.Config == nil { s.Config = &aws.Config{} } if s.Config.HTTPClient == nil { s.Config.HTTPClient = http.DefaultClient } if s.Config.SleepDelay == nil { s.Config.SleepDelay = time.Sleep } s.Retryer = DefaultRetryer{s} s.DefaultMaxRetries = 3 s.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) s.Handlers.Build.PushBackNamed(corehandlers.UserAgentHandler) s.Handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler) s.Handlers.Send.PushBackNamed(corehandlers.SendHandler) s.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) s.Handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler) if !aws.BoolValue(s.Config.DisableParamValidation) { s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler) } s.AddDebugHandlers() s.buildEndpoint() }
// hostStyleBucketName returns true if the request should put the bucket in // the host. This is false if S3ForcePathStyle is explicitly set or if the // bucket is not DNS compatible. func hostStyleBucketName(r *request.Request, bucket string) bool { if aws.BoolValue(r.Service.Config.S3ForcePathStyle) { return false } // Bucket might be DNS compatible but dots in the hostname will fail // certificate validation, so do not use host-style. if r.HTTPRequest.URL.Scheme == "https" && strings.Contains(bucket, ".") { return false } // Use host-style if the bucket is DNS compatible return dnsCompatibleBucketName(bucket) }
func setupChecksumValidation(r *request.Request) { if aws.BoolValue(r.Service.Config.DisableComputeChecksums) { return } switch r.Operation.Name { case opSendMessage: r.Handlers.Unmarshal.PushBack(verifySendMessage) case opSendMessageBatch: r.Handlers.Unmarshal.PushBack(verifySendMessageBatch) case opReceiveMessage: r.Handlers.Unmarshal.PushBack(verifyReceiveMessage) } }
// buildEndpoint builds the endpoint values the service will use to make requests with. func (s *Service) buildEndpoint() { if aws.StringValue(s.Config.Endpoint) != "" { s.Endpoint = *s.Config.Endpoint } else if s.Endpoint == "" { s.Endpoint, s.SigningRegion = endpoints.EndpointForRegion(s.ServiceName, aws.StringValue(s.Config.Region)) } if s.Endpoint != "" && !schemeRE.MatchString(s.Endpoint) { scheme := "https" if aws.BoolValue(s.Config.DisableSSL) { scheme = "http" } s.Endpoint = scheme + "://" + s.Endpoint } }
func validateCRC32(r *request.Request) { if r.Error != nil { return // already have an error, no need to verify CRC } // Checksum validation is off, skip if aws.BoolValue(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 = aws.Bool(true) r.Error = awserr.New("CRC32CheckFailed", "CRC32 integrity check failed", nil) } }
// WillRetry returns if the request's can be retried. func (r *Request) WillRetry() bool { return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries() }
// Send will send the request returning error if errors are encountered. // // Send will sign the request prior to sending. All Send Handlers will // be executed in the order they were set. func (r *Request) Send() error { for { r.Sign() if r.Error != nil { return r.Error } if aws.BoolValue(r.Retryable) { if r.Service.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) { r.Service.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d", r.Service.ServiceName, r.Operation.Name, r.RetryCount)) } // Re-seek the body back to the original point in for a retry so that // send will send the body's contents again in the upcoming request. r.Body.Seek(r.BodyStart, 0) r.HTTPRequest.Body = ioutil.NopCloser(r.Body) } r.Retryable = nil r.Handlers.Send.Run(r) if r.Error != nil { err := r.Error r.Handlers.Retry.Run(r) r.Handlers.AfterRetry.Run(r) if r.Error != nil { debugLogReqError(r, "Send Request", false, r.Error) return r.Error } debugLogReqError(r, "Send Request", true, err) continue } r.Handlers.UnmarshalMeta.Run(r) r.Handlers.ValidateResponse.Run(r) if r.Error != nil { err := r.Error r.Handlers.UnmarshalError.Run(r) r.Handlers.Retry.Run(r) r.Handlers.AfterRetry.Run(r) if r.Error != nil { debugLogReqError(r, "Validate Response", false, r.Error) return r.Error } debugLogReqError(r, "Validate Response", true, err) continue } r.Handlers.Unmarshal.Run(r) if r.Error != nil { err := r.Error r.Handlers.Retry.Run(r) r.Handlers.AfterRetry.Run(r) if r.Error != nil { debugLogReqError(r, "Unmarshal Response", false, r.Error) return r.Error } debugLogReqError(r, "Unmarshal Response", true, err) continue } break } return nil }