112 lines
2.3 KiB
Go
Executable File
112 lines
2.3 KiB
Go
Executable File
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()
|
||
for k := range vals {
|
||
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
|
||
}
|