123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- // This file is auto-generated, don't edit it. Thanks.
- /**
- * This is for OpenApi Util
- */
- package service
- import (
- "bytes"
- "crypto"
- "crypto/hmac"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha1"
- "crypto/sha256"
- "crypto/x509"
- "encoding/base64"
- "encoding/hex"
- "encoding/json"
- "encoding/pem"
- "errors"
- "fmt"
- "hash"
- "io"
- "net/http"
- "net/textproto"
- "net/url"
- "reflect"
- "sort"
- "strconv"
- "strings"
- "time"
- util "github.com/alibabacloud-go/tea-utils/v2/service"
- "github.com/alibabacloud-go/tea/tea"
- "github.com/tjfoc/gmsm/sm3"
- )
- const (
- PEM_BEGIN = "-----BEGIN RSA PRIVATE KEY-----\n"
- PEM_END = "\n-----END RSA PRIVATE KEY-----"
- )
- type Sorter struct {
- Keys []string
- Vals []string
- }
- func newSorter(m map[string]string) *Sorter {
- hs := &Sorter{
- Keys: make([]string, 0, len(m)),
- Vals: make([]string, 0, len(m)),
- }
- for k, v := range m {
- hs.Keys = append(hs.Keys, k)
- hs.Vals = append(hs.Vals, v)
- }
- return hs
- }
- // Sort is an additional function for function SignHeader.
- func (hs *Sorter) Sort() {
- sort.Sort(hs)
- }
- // Len is an additional function for function SignHeader.
- func (hs *Sorter) Len() int {
- return len(hs.Vals)
- }
- // Less is an additional function for function SignHeader.
- func (hs *Sorter) Less(i, j int) bool {
- return bytes.Compare([]byte(hs.Keys[i]), []byte(hs.Keys[j])) < 0
- }
- // Swap is an additional function for function SignHeader.
- func (hs *Sorter) Swap(i, j int) {
- hs.Vals[i], hs.Vals[j] = hs.Vals[j], hs.Vals[i]
- hs.Keys[i], hs.Keys[j] = hs.Keys[j], hs.Keys[i]
- }
- /**
- * Convert all params of body other than type of readable into content
- * @param body source Model
- * @param content target Model
- * @return void
- */
- func Convert(body interface{}, content interface{}) {
- res := make(map[string]interface{})
- val := reflect.ValueOf(body).Elem()
- dataType := val.Type()
- for i := 0; i < dataType.NumField(); i++ {
- field := dataType.Field(i)
- name, _ := field.Tag.Lookup("json")
- name = strings.Split(name, ",omitempty")[0]
- _, ok := val.Field(i).Interface().(io.Reader)
- if !ok {
- res[name] = val.Field(i).Interface()
- }
- }
- byt, _ := json.Marshal(res)
- json.Unmarshal(byt, content)
- }
- /**
- * Get the string to be signed according to request
- * @param request which contains signed messages
- * @return the signed string
- */
- func GetStringToSign(request *tea.Request) (_result *string) {
- return tea.String(getStringToSign(request))
- }
- func getStringToSign(request *tea.Request) string {
- resource := tea.StringValue(request.Pathname)
- queryParams := request.Query
- // sort QueryParams by key
- var queryKeys []string
- for key := range queryParams {
- queryKeys = append(queryKeys, key)
- }
- sort.Strings(queryKeys)
- tmp := ""
- for i := 0; i < len(queryKeys); i++ {
- queryKey := queryKeys[i]
- v := tea.StringValue(queryParams[queryKey])
- if v != "" {
- tmp = tmp + "&" + queryKey + "=" + v
- } else {
- tmp = tmp + "&" + queryKey
- }
- }
- if tmp != "" {
- tmp = strings.TrimLeft(tmp, "&")
- resource = resource + "?" + tmp
- }
- return getSignedStr(request, resource)
- }
- func getSignedStr(req *tea.Request, canonicalizedResource string) string {
- temp := make(map[string]string)
- for k, v := range req.Headers {
- if strings.HasPrefix(strings.ToLower(k), "x-acs-") {
- temp[strings.ToLower(k)] = tea.StringValue(v)
- }
- }
- hs := newSorter(temp)
- // Sort the temp by the ascending order
- hs.Sort()
- // Get the canonicalizedOSSHeaders
- canonicalizedOSSHeaders := ""
- for i := range hs.Keys {
- canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n"
- }
- // Give other parameters values
- // when sign URL, date is expires
- date := tea.StringValue(req.Headers["date"])
- accept := tea.StringValue(req.Headers["accept"])
- contentType := tea.StringValue(req.Headers["content-type"])
- contentMd5 := tea.StringValue(req.Headers["content-md5"])
- signStr := tea.StringValue(req.Method) + "\n" + accept + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource
- return signStr
- }
- /**
- * Get signature according to stringToSign, secret
- * @param stringToSign the signed string
- * @param secret accesskey secret
- * @return the signature
- */
- func GetROASignature(stringToSign *string, secret *string) (_result *string) {
- h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(tea.StringValue(secret)))
- io.WriteString(h, tea.StringValue(stringToSign))
- signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
- return tea.String(signedStr)
- }
- func GetEndpoint(endpoint *string, server *bool, endpointType *string) *string {
- if tea.StringValue(endpointType) == "internal" {
- strs := strings.Split(tea.StringValue(endpoint), ".")
- strs[0] += "-internal"
- endpoint = tea.String(strings.Join(strs, "."))
- }
- if tea.BoolValue(server) && tea.StringValue(endpointType) == "accelerate" {
- return tea.String("oss-accelerate.aliyuncs.com")
- }
- return endpoint
- }
- func HexEncode(raw []byte) *string {
- return tea.String(hex.EncodeToString(raw))
- }
- func Hash(raw []byte, signatureAlgorithm *string) []byte {
- signType := tea.StringValue(signatureAlgorithm)
- if signType == "ACS3-HMAC-SHA256" || signType == "ACS3-RSA-SHA256" {
- h := sha256.New()
- h.Write(raw)
- return h.Sum(nil)
- } else if signType == "ACS3-HMAC-SM3" {
- h := sm3.New()
- h.Write(raw)
- return h.Sum(nil)
- }
- return nil
- }
- func GetEncodePath(path *string) *string {
- uri := tea.StringValue(path)
- strs := strings.Split(uri, "/")
- for i, v := range strs {
- strs[i] = url.QueryEscape(v)
- }
- uri = strings.Join(strs, "/")
- uri = strings.Replace(uri, "+", "%20", -1)
- uri = strings.Replace(uri, "*", "%2A", -1)
- uri = strings.Replace(uri, "%7E", "~", -1)
- return tea.String(uri)
- }
- func GetEncodeParam(param *string) *string {
- uri := tea.StringValue(param)
- uri = url.QueryEscape(uri)
- uri = strings.Replace(uri, "+", "%20", -1)
- uri = strings.Replace(uri, "*", "%2A", -1)
- uri = strings.Replace(uri, "%7E", "~", -1)
- return tea.String(uri)
- }
- func GetAuthorization(request *tea.Request, signatureAlgorithm, payload, acesskey, secret *string) *string {
- canonicalURI := tea.StringValue(request.Pathname)
- if canonicalURI == "" {
- canonicalURI = "/"
- }
- canonicalURI = strings.Replace(canonicalURI, "+", "%20", -1)
- canonicalURI = strings.Replace(canonicalURI, "*", "%2A", -1)
- canonicalURI = strings.Replace(canonicalURI, "%7E", "~", -1)
- method := tea.StringValue(request.Method)
- canonicalQueryString := getCanonicalQueryString(request.Query)
- canonicalheaders, signedHeaders := getCanonicalHeaders(request.Headers)
- canonicalRequest := method + "\n" + canonicalURI + "\n" + canonicalQueryString + "\n" + canonicalheaders + "\n" +
- strings.Join(signedHeaders, ";") + "\n" + tea.StringValue(payload)
- signType := tea.StringValue(signatureAlgorithm)
- StringToSign := signType + "\n" + tea.StringValue(HexEncode(Hash([]byte(canonicalRequest), signatureAlgorithm)))
- signature := tea.StringValue(HexEncode(SignatureMethod(tea.StringValue(secret), StringToSign, signType)))
- auth := signType + " Credential=" + tea.StringValue(acesskey) + ",SignedHeaders=" +
- strings.Join(signedHeaders, ";") + ",Signature=" + signature
- return tea.String(auth)
- }
- func SignatureMethod(secret, source, signatureAlgorithm string) []byte {
- if signatureAlgorithm == "ACS3-HMAC-SHA256" {
- h := hmac.New(sha256.New, []byte(secret))
- h.Write([]byte(source))
- return h.Sum(nil)
- } else if signatureAlgorithm == "ACS3-HMAC-SM3" {
- h := hmac.New(sm3.New, []byte(secret))
- h.Write([]byte(source))
- return h.Sum(nil)
- } else if signatureAlgorithm == "ACS3-RSA-SHA256" {
- return rsaSign(source, secret)
- }
- return nil
- }
- func rsaSign(content, secret string) []byte {
- h := crypto.SHA256.New()
- h.Write([]byte(content))
- hashed := h.Sum(nil)
- priv, err := parsePrivateKey(secret)
- if err != nil {
- return nil
- }
- sign, err := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, hashed)
- if err != nil {
- return nil
- }
- return sign
- }
- func parsePrivateKey(privateKey string) (*rsa.PrivateKey, error) {
- privateKey = formatPrivateKey(privateKey)
- block, _ := pem.Decode([]byte(privateKey))
- if block == nil {
- return nil, errors.New("PrivateKey is invalid")
- }
- priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
- if err != nil {
- return nil, err
- }
- switch priKey.(type) {
- case *rsa.PrivateKey:
- return priKey.(*rsa.PrivateKey), nil
- default:
- return nil, nil
- }
- }
- func formatPrivateKey(privateKey string) string {
- if !strings.HasPrefix(privateKey, PEM_BEGIN) {
- privateKey = PEM_BEGIN + privateKey
- }
- if !strings.HasSuffix(privateKey, PEM_END) {
- privateKey += PEM_END
- }
- return privateKey
- }
- func getCanonicalHeaders(headers map[string]*string) (string, []string) {
- tmp := make(map[string]string)
- tmpHeader := http.Header{}
- for k, v := range headers {
- if strings.HasPrefix(strings.ToLower(k), "x-acs-") || strings.ToLower(k) == "host" ||
- strings.ToLower(k) == "content-type" {
- tmp[strings.ToLower(k)] = strings.TrimSpace(tea.StringValue(v))
- tmpHeader.Add(strings.ToLower(k), strings.TrimSpace(tea.StringValue(v)))
- }
- }
- hs := newSorter(tmp)
- // Sort the temp by the ascending order
- hs.Sort()
- canonicalheaders := ""
- for _, key := range hs.Keys {
- vals := tmpHeader[textproto.CanonicalMIMEHeaderKey(key)]
- sort.Strings(vals)
- canonicalheaders += key + ":" + strings.Join(vals, ",") + "\n"
- }
- return canonicalheaders, hs.Keys
- }
- func getCanonicalQueryString(query map[string]*string) string {
- canonicalQueryString := ""
- if tea.BoolValue(util.IsUnset(query)) {
- return canonicalQueryString
- }
- tmp := make(map[string]string)
- for k, v := range query {
- tmp[k] = tea.StringValue(v)
- }
- hs := newSorter(tmp)
- // Sort the temp by the ascending order
- hs.Sort()
- for i := range hs.Keys {
- if hs.Vals[i] != "" {
- canonicalQueryString += "&" + hs.Keys[i] + "=" + url.QueryEscape(hs.Vals[i])
- } else {
- canonicalQueryString += "&" + hs.Keys[i] + "="
- }
- }
- canonicalQueryString = strings.Replace(canonicalQueryString, "+", "%20", -1)
- canonicalQueryString = strings.Replace(canonicalQueryString, "*", "%2A", -1)
- canonicalQueryString = strings.Replace(canonicalQueryString, "%7E", "~", -1)
- if canonicalQueryString != "" {
- canonicalQueryString = strings.TrimLeft(canonicalQueryString, "&")
- }
- return canonicalQueryString
- }
- /**
- * Parse filter into a form string
- * @param filter object
- * @return the string
- */
- func ToForm(filter map[string]interface{}) (_result *string) {
- tmp := make(map[string]interface{})
- byt, _ := json.Marshal(filter)
- d := json.NewDecoder(bytes.NewReader(byt))
- d.UseNumber()
- _ = d.Decode(&tmp)
- result := make(map[string]*string)
- for key, value := range tmp {
- filterValue := reflect.ValueOf(value)
- flatRepeatedList(filterValue, result, key)
- }
- m := util.AnyifyMapValue(result)
- return util.ToFormString(m)
- }
- func flatRepeatedList(dataValue reflect.Value, result map[string]*string, prefix string) {
- if !dataValue.IsValid() {
- return
- }
- dataType := dataValue.Type()
- if dataType.Kind().String() == "slice" {
- handleRepeatedParams(dataValue, result, prefix)
- } else if dataType.Kind().String() == "map" {
- handleMap(dataValue, result, prefix)
- } else {
- result[prefix] = tea.String(fmt.Sprintf("%v", dataValue.Interface()))
- }
- }
- func handleRepeatedParams(repeatedFieldValue reflect.Value, result map[string]*string, prefix string) {
- if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
- for m := 0; m < repeatedFieldValue.Len(); m++ {
- elementValue := repeatedFieldValue.Index(m)
- key := prefix + "." + strconv.Itoa(m+1)
- fieldValue := reflect.ValueOf(elementValue.Interface())
- if fieldValue.Kind().String() == "map" {
- handleMap(fieldValue, result, key)
- } else {
- result[key] = tea.String(fmt.Sprintf("%v", fieldValue.Interface()))
- }
- }
- }
- }
- func handleMap(valueField reflect.Value, result map[string]*string, prefix string) {
- if valueField.IsValid() && valueField.String() != "" {
- valueFieldType := valueField.Type()
- if valueFieldType.Kind().String() == "map" {
- var byt []byte
- byt, _ = json.Marshal(valueField.Interface())
- cache := make(map[string]interface{})
- d := json.NewDecoder(bytes.NewReader(byt))
- d.UseNumber()
- _ = d.Decode(&cache)
- for key, value := range cache {
- pre := ""
- if prefix != "" {
- pre = prefix + "." + key
- } else {
- pre = key
- }
- fieldValue := reflect.ValueOf(value)
- flatRepeatedList(fieldValue, result, pre)
- }
- }
- }
- }
- /**
- * Get timestamp
- * @return the timestamp string
- */
- func GetTimestamp() (_result *string) {
- gmt := time.FixedZone("GMT", 0)
- return tea.String(time.Now().In(gmt).Format("2006-01-02T15:04:05Z"))
- }
- /**
- * Parse filter into a object which's type is map[string]string
- * @param filter query param
- * @return the object
- */
- func Query(filter interface{}) (_result map[string]*string) {
- tmp := make(map[string]interface{})
- byt, _ := json.Marshal(filter)
- d := json.NewDecoder(bytes.NewReader(byt))
- d.UseNumber()
- _ = d.Decode(&tmp)
- result := make(map[string]*string)
- for key, value := range tmp {
- filterValue := reflect.ValueOf(value)
- flatRepeatedList(filterValue, result, key)
- }
- return result
- }
- /**
- * Get signature according to signedParams, method and secret
- * @param signedParams params which need to be signed
- * @param method http method e.g. GET
- * @param secret AccessKeySecret
- * @return the signature
- */
- func GetRPCSignature(signedParams map[string]*string, method *string, secret *string) (_result *string) {
- stringToSign := buildRpcStringToSign(signedParams, tea.StringValue(method))
- signature := sign(stringToSign, tea.StringValue(secret), "&")
- return tea.String(signature)
- }
- /**
- * Parse array into a string with specified style
- * @param array the array
- * @param prefix the prefix string
- * @style specified style e.g. repeatList
- * @return the string
- */
- func ArrayToStringWithSpecifiedStyle(array interface{}, prefix *string, style *string) (_result *string) {
- if tea.BoolValue(util.IsUnset(array)) {
- return tea.String("")
- }
- sty := tea.StringValue(style)
- if sty == "repeatList" {
- tmp := map[string]interface{}{
- tea.StringValue(prefix): array,
- }
- return flatRepeatList(tmp)
- } else if sty == "simple" || sty == "spaceDelimited" || sty == "pipeDelimited" {
- return flatArray(array, sty)
- } else if sty == "json" {
- return util.ToJSONString(array)
- }
- return tea.String("")
- }
- func ParseToMap(in interface{}) map[string]interface{} {
- if tea.BoolValue(util.IsUnset(in)) {
- return nil
- }
- tmp := make(map[string]interface{})
- byt, _ := json.Marshal(in)
- d := json.NewDecoder(bytes.NewReader(byt))
- d.UseNumber()
- err := d.Decode(&tmp)
- if err != nil {
- return nil
- }
- return tmp
- }
- func flatRepeatList(filter map[string]interface{}) (_result *string) {
- tmp := make(map[string]interface{})
- byt, _ := json.Marshal(filter)
- d := json.NewDecoder(bytes.NewReader(byt))
- d.UseNumber()
- _ = d.Decode(&tmp)
- result := make(map[string]*string)
- for key, value := range tmp {
- filterValue := reflect.ValueOf(value)
- flatRepeatedList(filterValue, result, key)
- }
- res := make(map[string]string)
- for k, v := range result {
- res[k] = tea.StringValue(v)
- }
- hs := newSorter(res)
- hs.Sort()
- // Get the canonicalizedOSSHeaders
- t := ""
- for i := range hs.Keys {
- if i == len(hs.Keys)-1 {
- t += hs.Keys[i] + "=" + hs.Vals[i]
- } else {
- t += hs.Keys[i] + "=" + hs.Vals[i] + "&&"
- }
- }
- return tea.String(t)
- }
- func flatArray(array interface{}, sty string) *string {
- t := reflect.ValueOf(array)
- strs := make([]string, 0)
- for i := 0; i < t.Len(); i++ {
- tmp := t.Index(i)
- if tmp.Kind() == reflect.Ptr || tmp.Kind() == reflect.Interface {
- tmp = tmp.Elem()
- }
- if tmp.Kind() == reflect.Ptr {
- tmp = tmp.Elem()
- }
- if tmp.Kind() == reflect.String {
- strs = append(strs, tmp.String())
- } else {
- inter := tmp.Interface()
- byt, _ := json.Marshal(inter)
- strs = append(strs, string(byt))
- }
- }
- str := ""
- if sty == "simple" {
- str = strings.Join(strs, ",")
- } else if sty == "spaceDelimited" {
- str = strings.Join(strs, " ")
- } else if sty == "pipeDelimited" {
- str = strings.Join(strs, "|")
- }
- return tea.String(str)
- }
- func buildRpcStringToSign(signedParam map[string]*string, method string) (stringToSign string) {
- signParams := make(map[string]string)
- for key, value := range signedParam {
- signParams[key] = tea.StringValue(value)
- }
- stringToSign = getUrlFormedMap(signParams)
- stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
- stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
- stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
- stringToSign = url.QueryEscape(stringToSign)
- stringToSign = method + "&%2F&" + stringToSign
- return
- }
- func getUrlFormedMap(source map[string]string) (urlEncoded string) {
- urlEncoder := url.Values{}
- for key, value := range source {
- urlEncoder.Add(key, value)
- }
- urlEncoded = urlEncoder.Encode()
- return
- }
- func sign(stringToSign, accessKeySecret, secretSuffix string) string {
- secret := accessKeySecret + secretSuffix
- signedBytes := shaHmac1(stringToSign, secret)
- signedString := base64.StdEncoding.EncodeToString(signedBytes)
- return signedString
- }
- func shaHmac1(source, secret string) []byte {
- key := []byte(secret)
- hmac := hmac.New(sha1.New, key)
- hmac.Write([]byte(source))
- return hmac.Sum(nil)
- }
- func getTimeLeft(rateLimit *string) (_result *int64) {
- if rateLimit != nil {
- pairs := strings.Split(tea.StringValue(rateLimit), ",")
- for _, pair := range pairs {
- kv := strings.Split(pair, ":")
- if len(kv) == 2 {
- key, value := kv[0], kv[1]
- if key == "TimeLeft" {
- timeLeftValue, err := strconv.ParseInt(value, 10, 64)
- if err != nil {
- return nil
- }
- return tea.Int64(timeLeftValue)
- }
- }
- }
- }
- return nil
- }
- /**
- * Get throttling param
- * @param the response headers
- * @return time left
- */
- func GetThrottlingTimeLeft(headers map[string]*string) (_result *int64) {
- rateLimitForUserApi := headers["x-ratelimit-user-api"]
- rateLimitForUser := headers["x-ratelimit-user"]
- timeLeftForUserApi := getTimeLeft(rateLimitForUserApi)
- timeLeftForUser := getTimeLeft(rateLimitForUser)
- if tea.Int64Value(timeLeftForUserApi) > tea.Int64Value(timeLeftForUser) {
- return timeLeftForUserApi
- } else {
- return timeLeftForUser
- }
- }
|