Files
doc_ai_backed/vendor/github.com/alibabacloud-go/openapi-util/service/service.go
liuyuanchuang 48e63894eb init repo
2025-12-10 18:33:37 +08:00

636 lines
17 KiB
Go

// 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/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)
}