Skip to content

Commit da71747

Browse files
authored
Merge pull request #28 from nemunaire/b/signedurl_for_custom_endpoint
Rework presign function to allow signature of clients with dedicated endpoint
2 parents 083b555 + bb9a56d commit da71747

2 files changed

Lines changed: 28 additions & 22 deletions

File tree

presigned.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"crypto/sha256"
66
"encoding/hex"
77
"net/url"
8+
"path"
89
"sort"
910
"strconv"
1011
"strings"
@@ -24,8 +25,6 @@ type PresignedInput struct {
2425
Timestamp time.Time
2526
ExtraHeaders map[string]string
2627
ExpirySeconds int
27-
Protocol string
28-
Endpoint string
2928
}
3029

3130
// GeneratePresignedURL creates a Presigned URL that can be used
@@ -35,8 +34,9 @@ func (s3 *S3) GeneratePresignedURL(in PresignedInput) string {
3534
var (
3635
nowTime = nowTime()
3736

38-
protocol = defaultProtocol
39-
endpoint = defaultPresignedHost
37+
protocol = defaultProtocol
38+
hostname = defaultPresignedHost
39+
path_prefix = ""
4040
)
4141
if !in.Timestamp.IsZero() {
4242
nowTime = in.Timestamp.UTC()
@@ -52,28 +52,30 @@ func (s3 *S3) GeneratePresignedURL(in PresignedInput) string {
5252
b.Reset()
5353

5454
// Set the protocol as default if not provided.
55-
if in.Protocol != "" {
56-
protocol = in.Protocol
57-
}
58-
if in.Endpoint != "" {
59-
endpoint = in.Endpoint
55+
if endpoint, _ := url.Parse(s3.Endpoint); endpoint.Host != "" {
56+
protocol = endpoint.Scheme + "://"
57+
hostname = endpoint.Host
58+
path_prefix = path.Join("/", endpoint.Path, in.Bucket)
59+
} else {
60+
host := bytes.Buffer{}
61+
host.WriteString(in.Bucket)
62+
host.WriteRune('.')
63+
host.WriteString(hostname)
64+
hostname = host.String()
6065
}
6166

6267
// Add host to Headers
6368
signedHeaders := map[string][]byte{}
6469
for k, v := range in.ExtraHeaders {
6570
signedHeaders[k] = []byte(v)
6671
}
67-
host := bytes.Buffer{}
68-
host.WriteString(in.Bucket)
69-
host.WriteRune('.')
70-
host.WriteString(endpoint)
71-
signedHeaders["host"] = host.Bytes()
72+
signedHeaders["host"] = []byte(hostname)
7273

7374
// Start Canonical Request Formation
7475
h := sha256.New() // We write the canonical request directly to the SHA256 hash.
7576
h.Write([]byte(in.Method)) // HTTP Verb
7677
h.Write(newLine)
78+
h.Write([]byte(path_prefix))
7779
h.Write([]byte{'/'})
7880
h.Write([]byte(in.ObjectKey)) // CanonicalURL
7981
h.Write(newLine)
@@ -193,10 +195,14 @@ func (s3 *S3) GeneratePresignedURL(in PresignedInput) string {
193195
b.Reset()
194196

195197
// Start Generating URL
196-
b.WriteString(protocol)
197-
b.WriteString(in.Bucket)
198-
b.WriteRune('.')
199-
b.WriteString(endpoint)
198+
if s3.Endpoint != "" {
199+
b.WriteString(s3.Endpoint)
200+
b.WriteRune('/')
201+
b.WriteString(in.Bucket)
202+
} else {
203+
b.WriteString(protocol)
204+
b.WriteString(hostname)
205+
}
200206
b.WriteRune('/')
201207
b.WriteString(in.ObjectKey)
202208
b.WriteRune('?')

presigned_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ func TestS3_GeneratePresignedURL_Personal(t *testing.T) {
6060
os.Getenv("AWS_S3_ACCESS_KEY"),
6161
os.Getenv("AWS_S3_SECRET_KEY"),
6262
)
63+
s.Endpoint = os.Getenv("AWS_S3_ENDPOINT")
6364
dontwant := ""
6465
if got := s.GeneratePresignedURL(PresignedInput{
6566
Bucket: os.Getenv("AWS_S3_BUCKET"),
66-
Endpoint: os.Getenv("AWS_S3_ENDPOINT"),
6767
ObjectKey: "test1.txt",
6868
Method: "GET",
6969
Timestamp: nowTime(),
@@ -81,10 +81,10 @@ func TestS3_GeneratePresignedURL_ExtraHeader(t *testing.T) {
8181
os.Getenv("AWS_S3_ACCESS_KEY"),
8282
os.Getenv("AWS_S3_SECRET_KEY"),
8383
)
84+
s.Endpoint = os.Getenv("AWS_S3_ENDPOINT")
8485
dontwant := ""
8586
if got := s.GeneratePresignedURL(PresignedInput{
8687
Bucket: os.Getenv("AWS_S3_BUCKET"),
87-
Endpoint: os.Getenv("AWS_S3_ENDPOINT"),
8888
ObjectKey: "test2.txt",
8989
Method: "GET",
9090
Timestamp: nowTime(),
@@ -105,10 +105,10 @@ func TestS3_GeneratePresignedURL_PUT(t *testing.T) {
105105
os.Getenv("AWS_S3_ACCESS_KEY"),
106106
os.Getenv("AWS_S3_SECRET_KEY"),
107107
)
108+
s.Endpoint = os.Getenv("AWS_S3_ENDPOINT")
108109
dontwant := ""
109110
if got := s.GeneratePresignedURL(PresignedInput{
110111
Bucket: os.Getenv("AWS_S3_BUCKET"),
111-
Endpoint: os.Getenv("AWS_S3_ENDPOINT"),
112112
ObjectKey: "test2.txt",
113113
Method: "PUT",
114114
Timestamp: nowTime(),
@@ -126,13 +126,13 @@ func BenchmarkS3_GeneratePresigned(b *testing.B) {
126126
os.Getenv("AWS_S3_ACCESS_KEY"),
127127
os.Getenv("AWS_S3_SECRET_KEY"),
128128
)
129+
s.Endpoint = os.Getenv("AWS_S3_ENDPOINT")
129130

130131
b.ReportAllocs()
131132
b.ResetTimer()
132133
for n := 0; n < b.N; n++ {
133134
s.GeneratePresignedURL(PresignedInput{
134135
Bucket: os.Getenv("AWS_S3_BUCKET"),
135-
Endpoint: os.Getenv("AWS_S3_ENDPOINT"),
136136
ObjectKey: "test.txt",
137137
Method: "GET",
138138
Timestamp: nowTime(),

0 commit comments

Comments
 (0)