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