1package s3
2
3import (
4	"io/ioutil"
5	"regexp"
6
7	"github.com/aws/aws-sdk-go/aws"
8	"github.com/aws/aws-sdk-go/aws/awserr"
9	"github.com/aws/aws-sdk-go/aws/awsutil"
10	"github.com/aws/aws-sdk-go/aws/request"
11)
12
13var reBucketLocation = regexp.MustCompile(`>([^<>]+)<\/Location`)
14
15// NormalizeBucketLocation is a utility function which will update the
16// passed in value to always be a region ID. Generally this would be used
17// with GetBucketLocation API operation.
18//
19// Replaces empty string with "us-east-1", and "EU" with "eu-west-1".
20//
21// See http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html
22// for more information on the values that can be returned.
23func NormalizeBucketLocation(loc string) string {
24	switch loc {
25	case "":
26		loc = "us-east-1"
27	case "EU":
28		loc = "eu-west-1"
29	}
30
31	return loc
32}
33
34// NormalizeBucketLocationHandler is a request handler which will update the
35// GetBucketLocation's result LocationConstraint value to always be a region ID.
36//
37// Replaces empty string with "us-east-1", and "EU" with "eu-west-1".
38//
39// See http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html
40// for more information on the values that can be returned.
41//
42//     req, result := svc.GetBucketLocationRequest(&s3.GetBucketLocationInput{
43//         Bucket: aws.String(bucket),
44//     })
45//     req.Handlers.Unmarshal.PushBackNamed(NormalizeBucketLocationHandler)
46//     err := req.Send()
47var NormalizeBucketLocationHandler = request.NamedHandler{
48	Name: "awssdk.s3.NormalizeBucketLocation",
49	Fn: func(req *request.Request) {
50		if req.Error != nil {
51			return
52		}
53
54		out := req.Data.(*GetBucketLocationOutput)
55		loc := NormalizeBucketLocation(aws.StringValue(out.LocationConstraint))
56		out.LocationConstraint = aws.String(loc)
57	},
58}
59
60// WithNormalizeBucketLocation is a request option which will update the
61// GetBucketLocation's result LocationConstraint value to always be a region ID.
62//
63// Replaces empty string with "us-east-1", and "EU" with "eu-west-1".
64//
65// See http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html
66// for more information on the values that can be returned.
67//
68//     result, err := svc.GetBucketLocationWithContext(ctx,
69//         &s3.GetBucketLocationInput{
70//             Bucket: aws.String(bucket),
71//         },
72//         s3.WithNormalizeBucketLocation,
73//     )
74func WithNormalizeBucketLocation(r *request.Request) {
75	r.Handlers.Unmarshal.PushBackNamed(NormalizeBucketLocationHandler)
76}
77
78func buildGetBucketLocation(r *request.Request) {
79	if r.DataFilled() {
80		out := r.Data.(*GetBucketLocationOutput)
81		b, err := ioutil.ReadAll(r.HTTPResponse.Body)
82		if err != nil {
83			r.Error = awserr.New("SerializationError", "failed reading response body", err)
84			return
85		}
86
87		match := reBucketLocation.FindSubmatch(b)
88		if len(match) > 1 {
89			loc := string(match[1])
90			out.LocationConstraint = aws.String(loc)
91		}
92	}
93}
94
95func populateLocationConstraint(r *request.Request) {
96	if r.ParamsFilled() && aws.StringValue(r.Config.Region) != "us-east-1" {
97		in := r.Params.(*CreateBucketInput)
98		if in.CreateBucketConfiguration == nil {
99			r.Params = awsutil.CopyOf(r.Params)
100			in = r.Params.(*CreateBucketInput)
101			in.CreateBucketConfiguration = &CreateBucketConfiguration{
102				LocationConstraint: r.Config.Region,
103			}
104		}
105	}
106}
107