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) } }
// 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) } }
// CredChain returns the default credential chain. // // Generally you shouldn't need to use this method directly, but // is available if you need to reset the credentials of an // existing service client or session's Config. func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials { endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true) return credentials.NewCredentials(&credentials.ChainProvider{ VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors), Providers: []credentials.Provider{ &credentials.EnvProvider{}, &credentials.SharedCredentialsProvider{Filename: "", Profile: ""}, &ec2rolecreds.EC2RoleProvider{ Client: ec2metadata.NewClient(*cfg, handlers, endpoint, signingRegion), ExpiryWindow: 5 * time.Minute, }, }}) }
// 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.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 }
// NewClient returns a new EC2Metadata client. Should be used to create // a client when not using a session. Generally using just New with a session // is preferred. // // If an unmodified HTTP client is provided from the stdlib default, or no client // the EC2RoleProvider's EC2Metadata HTTP client's timeout will be shortened. // To disable this set Config.EC2MetadataDisableTimeoutOverride to false. Enabled by default. func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string, opts ...func(*client.Client)) *EC2Metadata { if !aws.BoolValue(cfg.EC2MetadataDisableTimeoutOverride) && httpClientZero(cfg.HTTPClient) { // If the http client is unmodified and this feature is not disabled // set custom timeouts for EC2Metadata requests. cfg.HTTPClient = &http.Client{ // use a shorter timeout than default because the metadata // service is local if it is running, and to fail faster // if not running on an ec2 instance. Timeout: 5 * time.Second, } } svc := &EC2Metadata{ Client: client.New( cfg, metadata.ClientInfo{ ServiceName: ServiceName, Endpoint: endpoint, APIVersion: "latest", }, handlers, ), } svc.Handlers.Unmarshal.PushBack(unmarshalHandler) svc.Handlers.UnmarshalError.PushBack(unmarshalError) svc.Handlers.Validate.Clear() svc.Handlers.Validate.PushBack(validateEndpointHandler) // Add additional options to the service config for _, option := range opts { option(svc.Client) } return svc }
// 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.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) { r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d", r.ClientInfo.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 }
// 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() }