func initHandlers(s *Session) { // Add the Validate parameter handler if it is not disabled. s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler) if !aws.BoolValue(s.Config.DisableParamValidation) { s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler) } }
// 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() }
// ClientConfig satisfies the client.ConfigProvider interface and is used to // configure the service client instances. Passing the Session to the service // client's constructor (New) will use this method to configure the client. // // Example: // sess := session.New() // s3.New(sess) func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config { s = s.Copy(cfgs...) endpoint, signingRegion := endpoints.NormalizeEndpoint( aws.StringValue(s.Config.Endpoint), serviceName, aws.StringValue(s.Config.Region), aws.BoolValue(s.Config.DisableSSL)) return client.Config{ Config: s.Config, Handlers: s.Handlers, Endpoint: endpoint, SigningRegion: signingRegion, } }
func setupChecksumValidation(r *request.Request) { if aws.BoolValue(r.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 } }
// 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 } // GetBucketLocation should be able to be called from any region within // a partition, and return the associated region of the bucket. if r.Operation.Name == opGetBucketLocation { return false } // Use host-style if the bucket is DNS compatible return dnsCompatibleBucketName(bucket) }
// nextPageTokens returns the tokens to use when asking for the next page of // data. func (r *Request) nextPageTokens() []interface{} { if r.Operation.Paginator == nil { return nil } if r.Operation.TruncationToken != "" { tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken) if len(tr) == 0 { return nil } switch v := tr[0].(type) { case *bool: if !aws.BoolValue(v) { return nil } case bool: if v == false { return nil } } } tokens := []interface{}{} tokenAdded := false for _, outToken := range r.Operation.OutputTokens { v, _ := awsutil.ValuesAtPath(r.Data, outToken) if len(v) > 0 { tokens = append(tokens, v[0]) tokenAdded = true } else { tokens = append(tokens, nil) } } if !tokenAdded { return nil } return tokens }
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.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, r.HTTPResponse.ContentLength) 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) } }
func fillPresignedURL(r *request.Request) { if !r.ParamsFilled() { return } origParams := r.Params.(*CopySnapshotInput) // Stop if PresignedURL/DestinationRegion is set if origParams.PresignedUrl != nil || origParams.DestinationRegion != nil { return } origParams.DestinationRegion = r.Config.Region newParams := awsutil.CopyOf(r.Params).(*CopySnapshotInput) // Create a new request based on the existing request. We will use this to // presign the CopySnapshot request against the source region. cfg := r.Config.Copy(aws.NewConfig(). WithEndpoint(""). WithRegion(aws.StringValue(origParams.SourceRegion))) clientInfo := r.ClientInfo clientInfo.Endpoint, clientInfo.SigningRegion = endpoints.EndpointForRegion( clientInfo.ServiceName, aws.StringValue(cfg.Region), aws.BoolValue(cfg.DisableSSL)) // Presign a CopySnapshot request with modified params req := request.New(*cfg, clientInfo, r.Handlers, r.Retryer, r.Operation, newParams, r.Data) url, err := req.Presign(5 * time.Minute) // 5 minutes should be enough. if err != nil { // bubble error back up to original request r.Error = err return } // We have our URL, set it on params origParams.PresignedUrl = &url }
// 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 }