2016-12-27 01:58:42 +00:00
|
|
|
|
package alils
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/hmac"
|
|
|
|
|
"crypto/sha1"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/url"
|
|
|
|
|
"sort"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// GMT location
|
|
|
|
|
var gmtLoc = time.FixedZone("GMT", 0)
|
|
|
|
|
|
|
|
|
|
// NowRFC1123 returns now time in RFC1123 format with GMT timezone,
|
|
|
|
|
// eg. "Mon, 02 Jan 2006 15:04:05 GMT".
|
|
|
|
|
func nowRFC1123() string {
|
|
|
|
|
return time.Now().In(gmtLoc).Format(time.RFC1123)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// signature calculates a request's signature digest.
|
|
|
|
|
func signature(project *LogProject, method, uri string,
|
|
|
|
|
headers map[string]string) (digest string, err error) {
|
|
|
|
|
var contentMD5, contentType, date, canoHeaders, canoResource string
|
|
|
|
|
var slsHeaderKeys sort.StringSlice
|
|
|
|
|
|
|
|
|
|
// SignString = VERB + "\n"
|
|
|
|
|
// + CONTENT-MD5 + "\n"
|
|
|
|
|
// + CONTENT-TYPE + "\n"
|
|
|
|
|
// + DATE + "\n"
|
|
|
|
|
// + CanonicalizedSLSHeaders + "\n"
|
|
|
|
|
// + CanonicalizedResource
|
|
|
|
|
|
|
|
|
|
if val, ok := headers["Content-MD5"]; ok {
|
|
|
|
|
contentMD5 = val
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if val, ok := headers["Content-Type"]; ok {
|
|
|
|
|
contentType = val
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
date, ok := headers["Date"]
|
|
|
|
|
if !ok {
|
|
|
|
|
err = fmt.Errorf("Can't find 'Date' header")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calc CanonicalizedSLSHeaders
|
|
|
|
|
slsHeaders := make(map[string]string, len(headers))
|
|
|
|
|
for k, v := range headers {
|
|
|
|
|
l := strings.TrimSpace(strings.ToLower(k))
|
|
|
|
|
if strings.HasPrefix(l, "x-sls-") {
|
|
|
|
|
slsHeaders[l] = strings.TrimSpace(v)
|
|
|
|
|
slsHeaderKeys = append(slsHeaderKeys, l)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sort.Sort(slsHeaderKeys)
|
|
|
|
|
for i, k := range slsHeaderKeys {
|
|
|
|
|
canoHeaders += k + ":" + slsHeaders[k]
|
|
|
|
|
if i+1 < len(slsHeaderKeys) {
|
|
|
|
|
canoHeaders += "\n"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calc CanonicalizedResource
|
|
|
|
|
u, err := url.Parse(uri)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
canoResource += url.QueryEscape(u.Path)
|
|
|
|
|
if u.RawQuery != "" {
|
|
|
|
|
var keys sort.StringSlice
|
|
|
|
|
|
|
|
|
|
vals := u.Query()
|
2017-04-20 02:56:09 +00:00
|
|
|
|
for k := range vals {
|
2016-12-27 01:58:42 +00:00
|
|
|
|
keys = append(keys, k)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sort.Sort(keys)
|
|
|
|
|
canoResource += "?"
|
|
|
|
|
for i, k := range keys {
|
|
|
|
|
if i > 0 {
|
|
|
|
|
canoResource += "&"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, v := range vals[k] {
|
|
|
|
|
canoResource += k + "=" + v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
signStr := method + "\n" +
|
|
|
|
|
contentMD5 + "\n" +
|
|
|
|
|
contentType + "\n" +
|
|
|
|
|
date + "\n" +
|
|
|
|
|
canoHeaders + "\n" +
|
|
|
|
|
canoResource
|
|
|
|
|
|
|
|
|
|
// Signature = base64(hmac-sha1(UTF8-Encoding-Of(SignString),AccessKeySecret))
|
|
|
|
|
mac := hmac.New(sha1.New, []byte(project.AccessKeySecret))
|
|
|
|
|
_, err = mac.Write([]byte(signStr))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
digest = base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
|
|
|
|
return
|
|
|
|
|
}
|