github.com/aavshr/aws-sdk-go@v1.41.3/service/s3/s3manager/bucket_region.go (about) 1 package s3manager 2 3 import ( 4 "github.com/aavshr/aws-sdk-go/aws" 5 "github.com/aavshr/aws-sdk-go/aws/client" 6 "github.com/aavshr/aws-sdk-go/aws/corehandlers" 7 "github.com/aavshr/aws-sdk-go/aws/credentials" 8 "github.com/aavshr/aws-sdk-go/aws/request" 9 "github.com/aavshr/aws-sdk-go/service/s3" 10 "github.com/aavshr/aws-sdk-go/service/s3/s3iface" 11 ) 12 13 // GetBucketRegion will attempt to get the region for a bucket using the 14 // regionHint to determine which AWS partition to perform the query on. 15 // 16 // The request will not be signed, and will not use your AWS credentials. 17 // 18 // A "NotFound" error code will be returned if the bucket does not exist in the 19 // AWS partition the regionHint belongs to. If the regionHint parameter is an 20 // empty string GetBucketRegion will fallback to the ConfigProvider's region 21 // config. If the regionHint is empty, and the ConfigProvider does not have a 22 // region value, an error will be returned.. 23 // 24 // For example to get the region of a bucket which exists in "eu-central-1" 25 // you could provide a region hint of "us-west-2". 26 // 27 // sess := session.Must(session.NewSession()) 28 // 29 // bucket := "my-bucket" 30 // region, err := s3manager.GetBucketRegion(ctx, sess, bucket, "us-west-2") 31 // if err != nil { 32 // if aerr, ok := err.(awserr.Error); ok && aerr.Code() == "NotFound" { 33 // fmt.Fprintf(os.Stderr, "unable to find bucket %s's region not found\n", bucket) 34 // } 35 // return err 36 // } 37 // fmt.Printf("Bucket %s is in %s region\n", bucket, region) 38 // 39 // By default the request will be made to the Amazon S3 endpoint using the Path 40 // style addressing. 41 // 42 // s3.us-west-2.amazonaws.com/bucketname 43 // 44 // This is not compatible with Amazon S3's FIPS endpoints. To override this 45 // behavior to use Virtual Host style addressing, provide a functional option 46 // that will set the Request's Config.S3ForcePathStyle to aws.Bool(false). 47 // 48 // region, err := s3manager.GetBucketRegion(ctx, sess, "bucketname", "us-west-2", func(r *request.Request) { 49 // r.S3ForcePathStyle = aws.Bool(false) 50 // }) 51 // 52 // To configure the GetBucketRegion to make a request via the Amazon 53 // S3 FIPS endpoints directly when a FIPS region name is not available, (e.g. 54 // fips-us-gov-west-1) set the Config.Endpoint on the Session, or client the 55 // utility is called with. The hint region will be ignored if an endpoint URL 56 // is configured on the session or client. 57 // 58 // sess, err := session.NewSession(&aws.Config{ 59 // Endpoint: aws.String("https://s3-fips.us-west-2.amazonaws.com"), 60 // }) 61 // 62 // region, err := s3manager.GetBucketRegion(context.Background(), sess, "bucketname", "") 63 func GetBucketRegion(ctx aws.Context, c client.ConfigProvider, bucket, regionHint string, opts ...request.Option) (string, error) { 64 var cfg aws.Config 65 if len(regionHint) != 0 { 66 cfg.Region = aws.String(regionHint) 67 } 68 svc := s3.New(c, &cfg) 69 return GetBucketRegionWithClient(ctx, svc, bucket, opts...) 70 } 71 72 const bucketRegionHeader = "X-Amz-Bucket-Region" 73 74 // GetBucketRegionWithClient is the same as GetBucketRegion with the exception 75 // that it takes a S3 service client instead of a Session. The regionHint is 76 // derived from the region the S3 service client was created in. 77 // 78 // By default the request will be made to the Amazon S3 endpoint using the Path 79 // style addressing. 80 // 81 // s3.us-west-2.amazonaws.com/bucketname 82 // 83 // This is not compatible with Amazon S3's FIPS endpoints. To override this 84 // behavior to use Virtual Host style addressing, provide a functional option 85 // that will set the Request's Config.S3ForcePathStyle to aws.Bool(false). 86 // 87 // region, err := s3manager.GetBucketRegionWithClient(ctx, client, "bucketname", func(r *request.Request) { 88 // r.S3ForcePathStyle = aws.Bool(false) 89 // }) 90 // 91 // To configure the GetBucketRegion to make a request via the Amazon 92 // S3 FIPS endpoints directly when a FIPS region name is not available, (e.g. 93 // fips-us-gov-west-1) set the Config.Endpoint on the Session, or client the 94 // utility is called with. The hint region will be ignored if an endpoint URL 95 // is configured on the session or client. 96 // 97 // region, err := s3manager.GetBucketRegionWithClient(context.Background(), 98 // s3.New(sess, &aws.Config{ 99 // Endpoint: aws.String("https://s3-fips.us-west-2.amazonaws.com"), 100 // }), 101 // "bucketname") 102 // 103 // See GetBucketRegion for more information. 104 func GetBucketRegionWithClient(ctx aws.Context, svc s3iface.S3API, bucket string, opts ...request.Option) (string, error) { 105 req, _ := svc.HeadBucketRequest(&s3.HeadBucketInput{ 106 Bucket: aws.String(bucket), 107 }) 108 req.Config.S3ForcePathStyle = aws.Bool(true) 109 110 req.Config.Credentials = credentials.AnonymousCredentials 111 req.SetContext(ctx) 112 113 // Disable HTTP redirects to prevent an invalid 301 from eating the response 114 // because Go's HTTP client will fail, and drop the response if an 301 is 115 // received without a location header. S3 will return a 301 without the 116 // location header for HeadObject API calls. 117 req.DisableFollowRedirects = true 118 119 var bucketRegion string 120 req.Handlers.Send.PushBack(func(r *request.Request) { 121 bucketRegion = r.HTTPResponse.Header.Get(bucketRegionHeader) 122 if len(bucketRegion) == 0 { 123 return 124 } 125 r.HTTPResponse.StatusCode = 200 126 r.HTTPResponse.Status = "OK" 127 r.Error = nil 128 }) 129 // Replace the endpoint validation handler to not require a region if an 130 // endpoint URL was specified. Since these requests are not authenticated, 131 // requiring a region is not needed when an endpoint URL is provided. 132 req.Handlers.Validate.Swap( 133 corehandlers.ValidateEndpointHandler.Name, 134 request.NamedHandler{ 135 Name: "validateEndpointWithoutRegion", 136 Fn: validateEndpointWithoutRegion, 137 }, 138 ) 139 140 req.ApplyOptions(opts...) 141 142 if err := req.Send(); err != nil { 143 return "", err 144 } 145 146 bucketRegion = s3.NormalizeBucketLocation(bucketRegion) 147 148 return bucketRegion, nil 149 } 150 151 func validateEndpointWithoutRegion(r *request.Request) { 152 // Check if the caller provided an explicit URL instead of one derived by 153 // the SDK's endpoint resolver. For GetBucketRegion, with an explicit 154 // endpoint URL, a region is not needed. If no endpoint URL is provided, 155 // fallback the SDK's standard endpoint validation handler. 156 if len(aws.StringValue(r.Config.Endpoint)) == 0 { 157 corehandlers.ValidateEndpointHandler.Fn(r) 158 } 159 }