1// Code generated by smithy-go-codegen DO NOT EDIT. 2 3package s3 4 5import ( 6 "context" 7 "errors" 8 "fmt" 9 awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" 10 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" 11 s3cust "github.com/aws/aws-sdk-go-v2/service/s3/internal/customizations" 12 "github.com/aws/aws-sdk-go-v2/service/s3/types" 13 "github.com/aws/smithy-go/middleware" 14 smithytime "github.com/aws/smithy-go/time" 15 smithyhttp "github.com/aws/smithy-go/transport/http" 16 smithywaiter "github.com/aws/smithy-go/waiter" 17 "time" 18) 19 20// This action is useful to determine if a bucket exists and you have permission to 21// access it. The action returns a 200 OK if the bucket exists and you have 22// permission to access it. If the bucket does not exist or you do not have 23// permission to access it, the HEAD request returns a generic 404 Not Found or 403 24// Forbidden code. A message body is not included, so you cannot determine the 25// exception beyond these error codes. To use this operation, you must have 26// permissions to perform the s3:ListBucket action. The bucket owner has this 27// permission by default and can grant this permission to others. For more 28// information about permissions, see Permissions Related to Bucket Subresource 29// Operations 30// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources) 31// and Managing Access Permissions to Your Amazon S3 Resources 32// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html). 33// To use this API against an access point, you must provide the alias of the 34// access point in place of the bucket name or specify the access point ARN. When 35// using the access point ARN, you must direct requests to the access point 36// hostname. The access point hostname takes the form 37// AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using the 38// Amazon Web Services SDKs, you provide the ARN in place of the bucket name. For 39// more information see, Using access points 40// (https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-access-points.html). 41func (c *Client) HeadBucket(ctx context.Context, params *HeadBucketInput, optFns ...func(*Options)) (*HeadBucketOutput, error) { 42 if params == nil { 43 params = &HeadBucketInput{} 44 } 45 46 result, metadata, err := c.invokeOperation(ctx, "HeadBucket", params, optFns, c.addOperationHeadBucketMiddlewares) 47 if err != nil { 48 return nil, err 49 } 50 51 out := result.(*HeadBucketOutput) 52 out.ResultMetadata = metadata 53 return out, nil 54} 55 56type HeadBucketInput struct { 57 58 // The bucket name. When using this action with an access point, you must direct 59 // requests to the access point hostname. The access point hostname takes the form 60 // AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this 61 // action with an access point through the Amazon Web Services SDKs, you provide 62 // the access point ARN in place of the bucket name. For more information about 63 // access point ARNs, see Using access points 64 // (https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-access-points.html) 65 // in the Amazon S3 User Guide. When using this action with Amazon S3 on Outposts, 66 // you must direct requests to the S3 on Outposts hostname. The S3 on Outposts 67 // hostname takes the form 68 // AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using 69 // this action using S3 on Outposts through the Amazon Web Services SDKs, you 70 // provide the Outposts bucket ARN in place of the bucket name. For more 71 // information about S3 on Outposts ARNs, see Using S3 on Outposts 72 // (https://docs.aws.amazon.com/AmazonS3/latest/userguide/S3onOutposts.html) in the 73 // Amazon S3 User Guide. 74 // 75 // This member is required. 76 Bucket *string 77 78 // The account ID of the expected bucket owner. If the bucket is owned by a 79 // different account, the request will fail with an HTTP 403 (Access Denied) error. 80 ExpectedBucketOwner *string 81 82 noSmithyDocumentSerde 83} 84 85type HeadBucketOutput struct { 86 // Metadata pertaining to the operation's result. 87 ResultMetadata middleware.Metadata 88 89 noSmithyDocumentSerde 90} 91 92func (c *Client) addOperationHeadBucketMiddlewares(stack *middleware.Stack, options Options) (err error) { 93 err = stack.Serialize.Add(&awsRestxml_serializeOpHeadBucket{}, middleware.After) 94 if err != nil { 95 return err 96 } 97 err = stack.Deserialize.Add(&awsRestxml_deserializeOpHeadBucket{}, middleware.After) 98 if err != nil { 99 return err 100 } 101 if err = addSetLoggerMiddleware(stack, options); err != nil { 102 return err 103 } 104 if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { 105 return err 106 } 107 if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { 108 return err 109 } 110 if err = addResolveEndpointMiddleware(stack, options); err != nil { 111 return err 112 } 113 if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil { 114 return err 115 } 116 if err = addRetryMiddlewares(stack, options); err != nil { 117 return err 118 } 119 if err = addHTTPSignerV4Middleware(stack, options); err != nil { 120 return err 121 } 122 if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { 123 return err 124 } 125 if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { 126 return err 127 } 128 if err = addClientUserAgent(stack); err != nil { 129 return err 130 } 131 if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { 132 return err 133 } 134 if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { 135 return err 136 } 137 if err = swapWithCustomHTTPSignerMiddleware(stack, options); err != nil { 138 return err 139 } 140 if err = addOpHeadBucketValidationMiddleware(stack); err != nil { 141 return err 142 } 143 if err = stack.Initialize.Add(newServiceMetadataMiddleware_opHeadBucket(options.Region), middleware.Before); err != nil { 144 return err 145 } 146 if err = addMetadataRetrieverMiddleware(stack); err != nil { 147 return err 148 } 149 if err = addHeadBucketUpdateEndpoint(stack, options); err != nil { 150 return err 151 } 152 if err = addResponseErrorMiddleware(stack); err != nil { 153 return err 154 } 155 if err = v4.AddContentSHA256HeaderMiddleware(stack); err != nil { 156 return err 157 } 158 if err = disableAcceptEncodingGzip(stack); err != nil { 159 return err 160 } 161 if err = addRequestResponseLogging(stack, options); err != nil { 162 return err 163 } 164 return nil 165} 166 167// HeadBucketAPIClient is a client that implements the HeadBucket operation. 168type HeadBucketAPIClient interface { 169 HeadBucket(context.Context, *HeadBucketInput, ...func(*Options)) (*HeadBucketOutput, error) 170} 171 172var _ HeadBucketAPIClient = (*Client)(nil) 173 174// BucketExistsWaiterOptions are waiter options for BucketExistsWaiter 175type BucketExistsWaiterOptions struct { 176 177 // Set of options to modify how an operation is invoked. These apply to all 178 // operations invoked for this client. Use functional options on operation call to 179 // modify this list for per operation behavior. 180 APIOptions []func(*middleware.Stack) error 181 182 // MinDelay is the minimum amount of time to delay between retries. If unset, 183 // BucketExistsWaiter will use default minimum delay of 5 seconds. Note that 184 // MinDelay must resolve to a value lesser than or equal to the MaxDelay. 185 MinDelay time.Duration 186 187 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 188 // to zero, BucketExistsWaiter will use default max delay of 120 seconds. Note that 189 // MaxDelay must resolve to value greater than or equal to the MinDelay. 190 MaxDelay time.Duration 191 192 // LogWaitAttempts is used to enable logging for waiter retry attempts 193 LogWaitAttempts bool 194 195 // Retryable is function that can be used to override the service defined 196 // waiter-behavior based on operation output, or returned error. This function is 197 // used by the waiter to decide if a state is retryable or a terminal state. By 198 // default service-modeled logic will populate this option. This option can thus be 199 // used to define a custom waiter state with fall-back to service-modeled waiter 200 // state mutators.The function returns an error in case of a failure state. In case 201 // of retry state, this function returns a bool value of true and nil error, while 202 // in case of success it returns a bool value of false and nil error. 203 Retryable func(context.Context, *HeadBucketInput, *HeadBucketOutput, error) (bool, error) 204} 205 206// BucketExistsWaiter defines the waiters for BucketExists 207type BucketExistsWaiter struct { 208 client HeadBucketAPIClient 209 210 options BucketExistsWaiterOptions 211} 212 213// NewBucketExistsWaiter constructs a BucketExistsWaiter. 214func NewBucketExistsWaiter(client HeadBucketAPIClient, optFns ...func(*BucketExistsWaiterOptions)) *BucketExistsWaiter { 215 options := BucketExistsWaiterOptions{} 216 options.MinDelay = 5 * time.Second 217 options.MaxDelay = 120 * time.Second 218 options.Retryable = bucketExistsStateRetryable 219 220 for _, fn := range optFns { 221 fn(&options) 222 } 223 return &BucketExistsWaiter{ 224 client: client, 225 options: options, 226 } 227} 228 229// Wait calls the waiter function for BucketExists waiter. The maxWaitDur is the 230// maximum wait duration the waiter will wait. The maxWaitDur is required and must 231// be greater than zero. 232func (w *BucketExistsWaiter) Wait(ctx context.Context, params *HeadBucketInput, maxWaitDur time.Duration, optFns ...func(*BucketExistsWaiterOptions)) error { 233 if maxWaitDur <= 0 { 234 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 235 } 236 237 options := w.options 238 for _, fn := range optFns { 239 fn(&options) 240 } 241 242 if options.MaxDelay <= 0 { 243 options.MaxDelay = 120 * time.Second 244 } 245 246 if options.MinDelay > options.MaxDelay { 247 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 248 } 249 250 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 251 defer cancelFn() 252 253 logger := smithywaiter.Logger{} 254 remainingTime := maxWaitDur 255 256 var attempt int64 257 for { 258 259 attempt++ 260 apiOptions := options.APIOptions 261 start := time.Now() 262 263 if options.LogWaitAttempts { 264 logger.Attempt = attempt 265 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 266 apiOptions = append(apiOptions, logger.AddLogger) 267 } 268 269 out, err := w.client.HeadBucket(ctx, params, func(o *Options) { 270 o.APIOptions = append(o.APIOptions, apiOptions...) 271 }) 272 273 retryable, err := options.Retryable(ctx, params, out, err) 274 if err != nil { 275 return err 276 } 277 if !retryable { 278 return nil 279 } 280 281 remainingTime -= time.Since(start) 282 if remainingTime < options.MinDelay || remainingTime <= 0 { 283 break 284 } 285 286 // compute exponential backoff between waiter retries 287 delay, err := smithywaiter.ComputeDelay( 288 attempt, options.MinDelay, options.MaxDelay, remainingTime, 289 ) 290 if err != nil { 291 return fmt.Errorf("error computing waiter delay, %w", err) 292 } 293 294 remainingTime -= delay 295 // sleep for the delay amount before invoking a request 296 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 297 return fmt.Errorf("request cancelled while waiting, %w", err) 298 } 299 } 300 return fmt.Errorf("exceeded max wait time for BucketExists waiter") 301} 302 303func bucketExistsStateRetryable(ctx context.Context, input *HeadBucketInput, output *HeadBucketOutput, err error) (bool, error) { 304 305 if err == nil { 306 return false, nil 307 } 308 309 if err != nil { 310 var errorType *types.NotFound 311 if errors.As(err, &errorType) { 312 return true, nil 313 } 314 } 315 316 return true, nil 317} 318 319// BucketNotExistsWaiterOptions are waiter options for BucketNotExistsWaiter 320type BucketNotExistsWaiterOptions struct { 321 322 // Set of options to modify how an operation is invoked. These apply to all 323 // operations invoked for this client. Use functional options on operation call to 324 // modify this list for per operation behavior. 325 APIOptions []func(*middleware.Stack) error 326 327 // MinDelay is the minimum amount of time to delay between retries. If unset, 328 // BucketNotExistsWaiter will use default minimum delay of 5 seconds. Note that 329 // MinDelay must resolve to a value lesser than or equal to the MaxDelay. 330 MinDelay time.Duration 331 332 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 333 // to zero, BucketNotExistsWaiter will use default max delay of 120 seconds. Note 334 // that MaxDelay must resolve to value greater than or equal to the MinDelay. 335 MaxDelay time.Duration 336 337 // LogWaitAttempts is used to enable logging for waiter retry attempts 338 LogWaitAttempts bool 339 340 // Retryable is function that can be used to override the service defined 341 // waiter-behavior based on operation output, or returned error. This function is 342 // used by the waiter to decide if a state is retryable or a terminal state. By 343 // default service-modeled logic will populate this option. This option can thus be 344 // used to define a custom waiter state with fall-back to service-modeled waiter 345 // state mutators.The function returns an error in case of a failure state. In case 346 // of retry state, this function returns a bool value of true and nil error, while 347 // in case of success it returns a bool value of false and nil error. 348 Retryable func(context.Context, *HeadBucketInput, *HeadBucketOutput, error) (bool, error) 349} 350 351// BucketNotExistsWaiter defines the waiters for BucketNotExists 352type BucketNotExistsWaiter struct { 353 client HeadBucketAPIClient 354 355 options BucketNotExistsWaiterOptions 356} 357 358// NewBucketNotExistsWaiter constructs a BucketNotExistsWaiter. 359func NewBucketNotExistsWaiter(client HeadBucketAPIClient, optFns ...func(*BucketNotExistsWaiterOptions)) *BucketNotExistsWaiter { 360 options := BucketNotExistsWaiterOptions{} 361 options.MinDelay = 5 * time.Second 362 options.MaxDelay = 120 * time.Second 363 options.Retryable = bucketNotExistsStateRetryable 364 365 for _, fn := range optFns { 366 fn(&options) 367 } 368 return &BucketNotExistsWaiter{ 369 client: client, 370 options: options, 371 } 372} 373 374// Wait calls the waiter function for BucketNotExists waiter. The maxWaitDur is the 375// maximum wait duration the waiter will wait. The maxWaitDur is required and must 376// be greater than zero. 377func (w *BucketNotExistsWaiter) Wait(ctx context.Context, params *HeadBucketInput, maxWaitDur time.Duration, optFns ...func(*BucketNotExistsWaiterOptions)) error { 378 if maxWaitDur <= 0 { 379 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 380 } 381 382 options := w.options 383 for _, fn := range optFns { 384 fn(&options) 385 } 386 387 if options.MaxDelay <= 0 { 388 options.MaxDelay = 120 * time.Second 389 } 390 391 if options.MinDelay > options.MaxDelay { 392 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 393 } 394 395 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 396 defer cancelFn() 397 398 logger := smithywaiter.Logger{} 399 remainingTime := maxWaitDur 400 401 var attempt int64 402 for { 403 404 attempt++ 405 apiOptions := options.APIOptions 406 start := time.Now() 407 408 if options.LogWaitAttempts { 409 logger.Attempt = attempt 410 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 411 apiOptions = append(apiOptions, logger.AddLogger) 412 } 413 414 out, err := w.client.HeadBucket(ctx, params, func(o *Options) { 415 o.APIOptions = append(o.APIOptions, apiOptions...) 416 }) 417 418 retryable, err := options.Retryable(ctx, params, out, err) 419 if err != nil { 420 return err 421 } 422 if !retryable { 423 return nil 424 } 425 426 remainingTime -= time.Since(start) 427 if remainingTime < options.MinDelay || remainingTime <= 0 { 428 break 429 } 430 431 // compute exponential backoff between waiter retries 432 delay, err := smithywaiter.ComputeDelay( 433 attempt, options.MinDelay, options.MaxDelay, remainingTime, 434 ) 435 if err != nil { 436 return fmt.Errorf("error computing waiter delay, %w", err) 437 } 438 439 remainingTime -= delay 440 // sleep for the delay amount before invoking a request 441 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 442 return fmt.Errorf("request cancelled while waiting, %w", err) 443 } 444 } 445 return fmt.Errorf("exceeded max wait time for BucketNotExists waiter") 446} 447 448func bucketNotExistsStateRetryable(ctx context.Context, input *HeadBucketInput, output *HeadBucketOutput, err error) (bool, error) { 449 450 if err != nil { 451 var errorType *types.NotFound 452 if errors.As(err, &errorType) { 453 return false, nil 454 } 455 } 456 457 return true, nil 458} 459 460func newServiceMetadataMiddleware_opHeadBucket(region string) *awsmiddleware.RegisterServiceMetadata { 461 return &awsmiddleware.RegisterServiceMetadata{ 462 Region: region, 463 ServiceID: ServiceID, 464 SigningName: "s3", 465 OperationName: "HeadBucket", 466 } 467} 468 469// getHeadBucketBucketMember returns a pointer to string denoting a provided bucket 470// member valueand a boolean indicating if the input has a modeled bucket name, 471func getHeadBucketBucketMember(input interface{}) (*string, bool) { 472 in := input.(*HeadBucketInput) 473 if in.Bucket == nil { 474 return nil, false 475 } 476 return in.Bucket, true 477} 478func addHeadBucketUpdateEndpoint(stack *middleware.Stack, options Options) error { 479 return s3cust.UpdateEndpoint(stack, s3cust.UpdateEndpointOptions{ 480 Accessor: s3cust.UpdateEndpointParameterAccessor{ 481 GetBucketFromInput: getHeadBucketBucketMember, 482 }, 483 UsePathStyle: options.UsePathStyle, 484 UseAccelerate: options.UseAccelerate, 485 SupportsAccelerate: true, 486 TargetS3ObjectLambda: false, 487 EndpointResolver: options.EndpointResolver, 488 EndpointResolverOptions: options.EndpointOptions, 489 UseDualstack: options.UseDualstack, 490 UseARNRegion: options.UseARNRegion, 491 DisableMultiRegionAccessPoints: options.DisableMultiRegionAccessPoints, 492 }) 493} 494