-
Notifications
You must be signed in to change notification settings - Fork 2
/
util.go
80 lines (73 loc) · 2.57 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package s3
import (
"net/url"
"strings"
)
// TrimKey removes leading and trailing slashes from the value.
// Generally, S3 keys don't have leading and trailing slashes so
// this serves as a convenient sanitization function.
func TrimKey(key string) string {
return strings.Trim(key, "/")
}
// EndpointRegionBucketKey returns the S3 endpoint, region, bucket, and key embedded in a URL.
// For details on how S3 urls are formed, please see the S3 docs:
// https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html
//
// S3 URL examples showing optional placement of bucket and region (whitespace added for alignment):
//
// virtual-style bucket, no region: http://bucket.s3 .amazonaws.com
// virtual-style bucket, with region: http://bucket.s3-aws-region.amazonaws.com
// path-style bucket, no region: http:// s3 .amazonaws.com/bucket
// path-style bucket, with region: http:// s3-aws-region.amazonaws.com/bucket
// path-style bucket, custom endpoint: http:// 42.43.44.45/bucket
func EndpointRegionBucketKey(address *url.URL) (endpoint, region, bucket, key string) {
bucket, key = BucketKey(address)
if address != nil {
region = extractRegion(address.Host)
if isAlternateEndpoint(address.Host) {
endpoint = address.Scheme + "://" + address.Host
}
}
return endpoint, region, bucket, key
}
// BucketKey returns the S3 bucket and key embedded in an S3 URL.
// For details on how s3 urls are formed, please see the S3 docs:
// https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html
func BucketKey(address *url.URL) (bucket, key string) {
if address == nil {
return "", ""
}
if isPathStyleAddress(address.Host) {
path := TrimKey(address.Path)
elements := strings.Split(path, "/")
bucket = elements[0]
if len(elements) > 1 {
key = strings.Join(elements[1:], "/")
}
} else {
bucket = extractVirtualBucket(address.Host)
key = TrimKey(address.Path)
}
return bucket, key
}
func isAlternateEndpoint(host string) bool {
return !strings.HasSuffix(host, ".amazonaws.com")
}
func isPathStyleAddress(host string) bool {
return isAlternateEndpoint(host) || strings.HasPrefix(host, "s3.") || strings.HasPrefix(host, "s3-")
}
func extractVirtualBucket(host string) string {
bucketEnd := strings.Index(host, ".s3")
if bucketEnd <= 0 {
return ""
}
return host[:bucketEnd]
}
func extractRegion(host string) string {
regionBegin := strings.Index(host, "s3") + 3
regionEnd := strings.Index(host, ".amazonaws.com")
if regionBegin < 0 || regionEnd <= regionBegin {
return ""
}
return host[regionBegin:regionEnd]
}