aboutsummaryrefslogtreecommitdiff
path: root/pipkin.go
diff options
context:
space:
mode:
Diffstat (limited to 'pipkin.go')
-rw-r--r--pipkin.go56
1 files changed, 21 insertions, 35 deletions
diff --git a/pipkin.go b/pipkin.go
index 556a493..7c787c0 100644
--- a/pipkin.go
+++ b/pipkin.go
@@ -14,12 +14,13 @@ import (
"io"
"log"
"net/http"
- "net/url"
"os"
"path"
"strings"
"syscall"
"time"
+
+ "pipkin/url"
)
type Pipkin struct {
@@ -305,15 +306,8 @@ func (pk *Pipkin) presignQuery(method string, host Host, key string) (string, er
amzBucket := pk.config.Buckets[host.Bucket]
amzDateShort := time.Now().UTC().Format("20060102")
+ amzDateLong := time.Now().UTC().Format("20060102T150405Z") // ISO 8601
- // The date needs to follow the ISO 8601 standard and must be formatted with
- // the "yyyyMMddTHHmmssZ" format.
- amzDateLong := time.Now().UTC().Format("20060102T150405Z")
-
- // amzAlgorithm identifies the version of AWS Signature and the algorithm
- // that you used to calculate the signature; for AWS Signature Version 4,
- // this value is AWS4-HMAC-SHA256--AWS Signature Version 4 (AWS4) and the
- // HMAC-SHA256 algorithm (HMAC-SHA256).
amzAlgorithm := "AWS4-HMAC-SHA256"
amzService := "s3"
@@ -321,22 +315,20 @@ func (pk *Pipkin) presignQuery(method string, host Host, key string) (string, er
amzCred := fmt.Sprintf("%s/%s/%s/%s/aws4_request", amzBucket.KeyID,
amzDateShort, amzBucket.Region, amzService)
- // Prefix current key with path value from pipkin.json; we support virtual
- // hosts, e.g. /example.com/index.html
- //
- // url.JoinPath() encodes the path, so we have to call url.PathUnescape()
- // on amzResource when we create our Prefix and the final signed URL.
- amzResource, err := url.JoinPath(host.Path, key)
- if err != nil {
- return "", err
- }
- var amzPrefix string
- if strings.HasSuffix(amzResource, "/") {
- if len(amzResource) > 1 {
- amzPrefix = strings.TrimPrefix(amzResource, "/")
- amzPrefix, _ = url.PathUnescape(amzPrefix)
+ var amzKey, amzPrefix string
+ amzKey = path.Join(host.Path, key)
+ if strings.HasSuffix(key, "/") {
+
+ // path.Join() strips trailing slash, but we need one for prefix
+ if !strings.HasSuffix(amzKey, "/") {
+ amzKey += "/"
}
- amzResource = "/"
+
+ // Request for non-root directory
+ if len(amzKey) > 1 {
+ amzPrefix = strings.TrimPrefix(amzKey, "/")
+ }
+ amzKey = "/"
}
// Seconds for which the generated presigned URL is valid; for example,
@@ -359,7 +351,7 @@ func (pk *Pipkin) presignQuery(method string, host Host, key string) (string, er
uri.Add("X-Amz-Date", amzDateLong)
uri.Add("X-Amz-Expires", amzExpires)
uri.Add("X-Amz-SignedHeaders", amzSignedHeaders)
- if strings.HasSuffix(amzResource, "/") {
+ if strings.HasSuffix(amzKey, "/") {
uri.Add("list-type", "2")
uri.Add("max-keys", "50000")
uri.Add("prefix", amzPrefix)
@@ -373,10 +365,9 @@ func (pk *Pipkin) presignQuery(method string, host Host, key string) (string, er
//
// host
// UNSIGNED-PAYLOAD
- uriEncoded := strings.Replace(uri.Encode(), "+", "%20", -1)
canonicalRequest := fmt.Sprintf("%s\n%s\n%s\nhost:%s\n\n%s\n%s", method,
- amzResource, uriEncoded, amzBucket.Host, amzSignedHeaders,
- "UNSIGNED-PAYLOAD")
+ strings.Replace(url.PathEscape(amzKey), "%2F", "/", -1), uri.Encode(),
+ amzBucket.Host, amzSignedHeaders, "UNSIGNED-PAYLOAD")
// <yyyymmdd>/<AWS Region>/s3/aws4_request
amzScope := fmt.Sprintf("%s/%s/%s/aws4_request", amzDateShort,
@@ -407,19 +398,14 @@ func (pk *Pipkin) presignQuery(method string, host Host, key string) (string, er
amzSignatureSha256 := hmac.New(sha256.New, signingKey.Sum(nil))
amzSignatureSha256.Write([]byte(strToSign))
- // Provides the signature to authenticate our request. This signature must
- // match the signature S3 calculates; otherwise, S3 denies the request.
amzSignatureSha256Hex := hex.EncodeToString(amzSignatureSha256.Sum(nil))
signedURL, err := url.Parse(amzBucket.Endpoint)
if err != nil {
return "", err
}
-
- // Build & encode signed URL! We've calculated everything we need, now.
uri.Add("X-Amz-Signature", amzSignatureSha256Hex)
- signedURL.Path, _ = url.PathUnescape(amzResource)
- uriEncoded = strings.Replace(uri.Encode(), "+", "%20", -1)
- signedURL.RawQuery = uriEncoded
+ signedURL.Path = amzKey
+ signedURL.RawQuery = uri.Encode()
return signedURL.String(), nil
}