diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/service/s3/host_style_bucket.go')
-rw-r--r-- | vendor/github.com/aws/aws-sdk-go/service/s3/host_style_bucket.go | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/service/s3/host_style_bucket.go b/vendor/github.com/aws/aws-sdk-go/service/s3/host_style_bucket.go new file mode 100644 index 0000000..ec3ffe4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/s3/host_style_bucket.go | |||
@@ -0,0 +1,162 @@ | |||
1 | package s3 | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "net/url" | ||
6 | "regexp" | ||
7 | "strings" | ||
8 | |||
9 | "github.com/aws/aws-sdk-go/aws" | ||
10 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
11 | "github.com/aws/aws-sdk-go/aws/awsutil" | ||
12 | "github.com/aws/aws-sdk-go/aws/request" | ||
13 | ) | ||
14 | |||
15 | // an operationBlacklist is a list of operation names that should a | ||
16 | // request handler should not be executed with. | ||
17 | type operationBlacklist []string | ||
18 | |||
19 | // Continue will return true of the Request's operation name is not | ||
20 | // in the blacklist. False otherwise. | ||
21 | func (b operationBlacklist) Continue(r *request.Request) bool { | ||
22 | for i := 0; i < len(b); i++ { | ||
23 | if b[i] == r.Operation.Name { | ||
24 | return false | ||
25 | } | ||
26 | } | ||
27 | return true | ||
28 | } | ||
29 | |||
30 | var accelerateOpBlacklist = operationBlacklist{ | ||
31 | opListBuckets, opCreateBucket, opDeleteBucket, | ||
32 | } | ||
33 | |||
34 | // Request handler to automatically add the bucket name to the endpoint domain | ||
35 | // if possible. This style of bucket is valid for all bucket names which are | ||
36 | // DNS compatible and do not contain "." | ||
37 | func updateEndpointForS3Config(r *request.Request) { | ||
38 | forceHostStyle := aws.BoolValue(r.Config.S3ForcePathStyle) | ||
39 | accelerate := aws.BoolValue(r.Config.S3UseAccelerate) | ||
40 | |||
41 | if accelerate && accelerateOpBlacklist.Continue(r) { | ||
42 | if forceHostStyle { | ||
43 | if r.Config.Logger != nil { | ||
44 | r.Config.Logger.Log("ERROR: aws.Config.S3UseAccelerate is not compatible with aws.Config.S3ForcePathStyle, ignoring S3ForcePathStyle.") | ||
45 | } | ||
46 | } | ||
47 | updateEndpointForAccelerate(r) | ||
48 | } else if !forceHostStyle && r.Operation.Name != opGetBucketLocation { | ||
49 | updateEndpointForHostStyle(r) | ||
50 | } | ||
51 | } | ||
52 | |||
53 | func updateEndpointForHostStyle(r *request.Request) { | ||
54 | bucket, ok := bucketNameFromReqParams(r.Params) | ||
55 | if !ok { | ||
56 | // Ignore operation requests if the bucketname was not provided | ||
57 | // if this is an input validation error the validation handler | ||
58 | // will report it. | ||
59 | return | ||
60 | } | ||
61 | |||
62 | if !hostCompatibleBucketName(r.HTTPRequest.URL, bucket) { | ||
63 | // bucket name must be valid to put into the host | ||
64 | return | ||
65 | } | ||
66 | |||
67 | moveBucketToHost(r.HTTPRequest.URL, bucket) | ||
68 | } | ||
69 | |||
70 | var ( | ||
71 | accelElem = []byte("s3-accelerate.dualstack.") | ||
72 | ) | ||
73 | |||
74 | func updateEndpointForAccelerate(r *request.Request) { | ||
75 | bucket, ok := bucketNameFromReqParams(r.Params) | ||
76 | if !ok { | ||
77 | // Ignore operation requests if the bucketname was not provided | ||
78 | // if this is an input validation error the validation handler | ||
79 | // will report it. | ||
80 | return | ||
81 | } | ||
82 | |||
83 | if !hostCompatibleBucketName(r.HTTPRequest.URL, bucket) { | ||
84 | r.Error = awserr.New("InvalidParameterException", | ||
85 | fmt.Sprintf("bucket name %s is not compatible with S3 Accelerate", bucket), | ||
86 | nil) | ||
87 | return | ||
88 | } | ||
89 | |||
90 | parts := strings.Split(r.HTTPRequest.URL.Host, ".") | ||
91 | if len(parts) < 3 { | ||
92 | r.Error = awserr.New("InvalidParameterExecption", | ||
93 | fmt.Sprintf("unable to update endpoint host for S3 accelerate, hostname invalid, %s", | ||
94 | r.HTTPRequest.URL.Host), nil) | ||
95 | return | ||
96 | } | ||
97 | |||
98 | if parts[0] == "s3" || strings.HasPrefix(parts[0], "s3-") { | ||
99 | parts[0] = "s3-accelerate" | ||
100 | } | ||
101 | for i := 1; i+1 < len(parts); i++ { | ||
102 | if parts[i] == aws.StringValue(r.Config.Region) { | ||
103 | parts = append(parts[:i], parts[i+1:]...) | ||
104 | break | ||
105 | } | ||
106 | } | ||
107 | |||
108 | r.HTTPRequest.URL.Host = strings.Join(parts, ".") | ||
109 | |||
110 | moveBucketToHost(r.HTTPRequest.URL, bucket) | ||
111 | } | ||
112 | |||
113 | // Attempts to retrieve the bucket name from the request input parameters. | ||
114 | // If no bucket is found, or the field is empty "", false will be returned. | ||
115 | func bucketNameFromReqParams(params interface{}) (string, bool) { | ||
116 | b, _ := awsutil.ValuesAtPath(params, "Bucket") | ||
117 | if len(b) == 0 { | ||
118 | return "", false | ||
119 | } | ||
120 | |||
121 | if bucket, ok := b[0].(*string); ok { | ||
122 | if bucketStr := aws.StringValue(bucket); bucketStr != "" { | ||
123 | return bucketStr, true | ||
124 | } | ||
125 | } | ||
126 | |||
127 | return "", false | ||
128 | } | ||
129 | |||
130 | // hostCompatibleBucketName returns true if the request should | ||
131 | // put the bucket in the host. This is false if S3ForcePathStyle is | ||
132 | // explicitly set or if the bucket is not DNS compatible. | ||
133 | func hostCompatibleBucketName(u *url.URL, bucket string) bool { | ||
134 | // Bucket might be DNS compatible but dots in the hostname will fail | ||
135 | // certificate validation, so do not use host-style. | ||
136 | if u.Scheme == "https" && strings.Contains(bucket, ".") { | ||
137 | return false | ||
138 | } | ||
139 | |||
140 | // if the bucket is DNS compatible | ||
141 | return dnsCompatibleBucketName(bucket) | ||
142 | } | ||
143 | |||
144 | var reDomain = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`) | ||
145 | var reIPAddress = regexp.MustCompile(`^(\d+\.){3}\d+$`) | ||
146 | |||
147 | // dnsCompatibleBucketName returns true if the bucket name is DNS compatible. | ||
148 | // Buckets created outside of the classic region MUST be DNS compatible. | ||
149 | func dnsCompatibleBucketName(bucket string) bool { | ||
150 | return reDomain.MatchString(bucket) && | ||
151 | !reIPAddress.MatchString(bucket) && | ||
152 | !strings.Contains(bucket, "..") | ||
153 | } | ||
154 | |||
155 | // moveBucketToHost moves the bucket name from the URI path to URL host. | ||
156 | func moveBucketToHost(u *url.URL, bucket string) { | ||
157 | u.Host = bucket + "." + u.Host | ||
158 | u.Path = strings.Replace(u.Path, "/{Bucket}", "", -1) | ||
159 | if u.Path == "" { | ||
160 | u.Path = "/" | ||
161 | } | ||
162 | } | ||