101 lines
3.1 KiB
Go
101 lines
3.1 KiB
Go
package tencentvod
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/QuantumNous/new-api/common"
|
|
"github.com/QuantumNous/new-api/service"
|
|
)
|
|
|
|
const vodService = "vod"
|
|
const vodAPIVersion = "2018-07-17"
|
|
|
|
func sha256hex(s string) string {
|
|
b := sha256.Sum256([]byte(s))
|
|
return hex.EncodeToString(b[:])
|
|
}
|
|
|
|
func hmacSha256(s, key string) []byte {
|
|
h := hmac.New(sha256.New, []byte(key))
|
|
_, _ = h.Write([]byte(s))
|
|
return h.Sum(nil)
|
|
}
|
|
|
|
func tc3Authorization(secretID, secretKey, host, action string, timestamp int64, payloadJSON []byte) string {
|
|
httpRequestMethod := "POST"
|
|
canonicalURI := "/"
|
|
canonicalQueryString := ""
|
|
actionLower := strings.ToLower(action)
|
|
canonicalHeaders := fmt.Sprintf("content-type:%s\nhost:%s\nx-tc-action:%s\n", "application/json", host, actionLower)
|
|
signedHeaders := "content-type;host;x-tc-action"
|
|
hashedRequestPayload := sha256hex(string(payloadJSON))
|
|
canonicalRequest := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s",
|
|
httpRequestMethod, canonicalURI, canonicalQueryString, canonicalHeaders, signedHeaders, hashedRequestPayload)
|
|
|
|
algorithm := "TC3-HMAC-SHA256"
|
|
requestTimestamp := strconv.FormatInt(timestamp, 10)
|
|
ts, _ := strconv.ParseInt(requestTimestamp, 10, 64)
|
|
t := time.Unix(ts, 0).UTC()
|
|
date := t.Format("2006-01-02")
|
|
credentialScope := fmt.Sprintf("%s/%s/tc3_request", date, vodService)
|
|
hashedCanonicalRequest := sha256hex(canonicalRequest)
|
|
string2sign := fmt.Sprintf("%s\n%s\n%s\n%s", algorithm, requestTimestamp, credentialScope, hashedCanonicalRequest)
|
|
|
|
secretDate := hmacSha256(date, "TC3"+secretKey)
|
|
secretService := hmacSha256(vodService, string(secretDate))
|
|
signingKey := hmacSha256("tc3_request", string(secretService))
|
|
signature := hex.EncodeToString(hmacSha256(string2sign, string(signingKey)))
|
|
|
|
return fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
|
|
algorithm, secretID, credentialScope, signedHeaders, signature)
|
|
}
|
|
|
|
func SignedPOSTJSON(proxy string, endpoint string, region string, cred Credentials, action string, payloadJSON []byte) (*http.Response, error) {
|
|
u, err := url.Parse(strings.TrimSpace(endpoint))
|
|
if err != nil || u.Host == "" {
|
|
return nil, fmt.Errorf("invalid endpoint URL")
|
|
}
|
|
if u.Scheme == "" {
|
|
u.Scheme = "https"
|
|
}
|
|
fullURL := u.Scheme + "://" + u.Host + "/"
|
|
host := u.Host
|
|
|
|
ts := common.GetTimestamp()
|
|
auth := tc3Authorization(cred.SecretID, cred.SecretKey, host, action, ts, payloadJSON)
|
|
|
|
req, err := http.NewRequest(http.MethodPost, fullURL, bytes.NewReader(payloadJSON))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", auth)
|
|
req.Header.Set("X-TC-Action", action)
|
|
req.Header.Set("X-TC-Version", vodAPIVersion)
|
|
req.Header.Set("X-TC-Timestamp", strconv.FormatInt(ts, 10))
|
|
if strings.TrimSpace(region) != "" {
|
|
req.Header.Set("X-TC-Region", strings.TrimSpace(region))
|
|
}
|
|
|
|
var client *http.Client
|
|
if strings.TrimSpace(proxy) != "" {
|
|
client, err = service.NewProxyHttpClient(strings.TrimSpace(proxy))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
client = service.GetHttpClient()
|
|
}
|
|
return client.Do(req)
|
|
}
|
|
|