123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630 |
- package service
- import (
- "bufio"
- "bytes"
- "crypto/md5"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "math/rand"
- "net/http"
- "net/url"
- "reflect"
- "runtime"
- "strconv"
- "strings"
- "sync/atomic"
- "time"
- "github.com/alibabacloud-go/tea/tea"
- )
- var defaultUserAgent = fmt.Sprintf("AlibabaCloud (%s; %s) Golang/%s Core/%s TeaDSL/1", runtime.GOOS, runtime.GOARCH, strings.Trim(runtime.Version(), "go"), "0.01")
- type ExtendsParameters struct {
- Headers map[string]*string `json:"headers,omitempty" xml:"headers,omitempty"`
- Queries map[string]*string `json:"queries,omitempty" xml:"queries,omitempty"`
- }
- func (s ExtendsParameters) String() string {
- return tea.Prettify(s)
- }
- func (s ExtendsParameters) GoString() string {
- return s.String()
- }
- func (s *ExtendsParameters) SetHeaders(v map[string]*string) *ExtendsParameters {
- s.Headers = v
- return s
- }
- func (s *ExtendsParameters) SetQueries(v map[string]*string) *ExtendsParameters {
- s.Queries = v
- return s
- }
- type RuntimeOptions struct {
- Autoretry *bool `json:"autoretry" xml:"autoretry"`
- IgnoreSSL *bool `json:"ignoreSSL" xml:"ignoreSSL"`
- Key *string `json:"key,omitempty" xml:"key,omitempty"`
- Cert *string `json:"cert,omitempty" xml:"cert,omitempty"`
- Ca *string `json:"ca,omitempty" xml:"ca,omitempty"`
- MaxAttempts *int `json:"maxAttempts" xml:"maxAttempts"`
- BackoffPolicy *string `json:"backoffPolicy" xml:"backoffPolicy"`
- BackoffPeriod *int `json:"backoffPeriod" xml:"backoffPeriod"`
- ReadTimeout *int `json:"readTimeout" xml:"readTimeout"`
- ConnectTimeout *int `json:"connectTimeout" xml:"connectTimeout"`
- LocalAddr *string `json:"localAddr" xml:"localAddr"`
- HttpProxy *string `json:"httpProxy" xml:"httpProxy"`
- HttpsProxy *string `json:"httpsProxy" xml:"httpsProxy"`
- NoProxy *string `json:"noProxy" xml:"noProxy"`
- MaxIdleConns *int `json:"maxIdleConns" xml:"maxIdleConns"`
- Socks5Proxy *string `json:"socks5Proxy" xml:"socks5Proxy"`
- Socks5NetWork *string `json:"socks5NetWork" xml:"socks5NetWork"`
- KeepAlive *bool `json:"keepAlive" xml:"keepAlive"`
- ExtendsParameters *ExtendsParameters `json:"extendsParameters,omitempty" xml:"extendsParameters,omitempty"`
- }
- var processStartTime int64 = time.Now().UnixNano() / 1e6
- var seqId int64 = 0
- type SSEEvent struct {
- ID *string
- Event *string
- Data *string
- Retry *int
- }
- func parseEvent(eventLines []string) (SSEEvent, error) {
- var event SSEEvent
- for _, line := range eventLines {
- if strings.HasPrefix(line, "data:") {
- event.Data = tea.String(tea.StringValue(event.Data) + strings.TrimPrefix(line, "data:") + "\n")
- } else if strings.HasPrefix(line, "id:") {
- id := strings.TrimPrefix(line, "id:")
- event.ID = tea.String(strings.Trim(id, " "))
- } else if strings.HasPrefix(line, "event:") {
- eventName := strings.TrimPrefix(line, "event:")
- event.Event = tea.String(strings.Trim(eventName, " "))
- } else if strings.HasPrefix(line, "retry:") {
- trimmedLine := strings.TrimPrefix(line, "retry:")
- trimmedLine = strings.Trim(trimmedLine, " ")
- retryValue, _err := strconv.Atoi(trimmedLine)
- if _err != nil {
- return event, fmt.Errorf("retry %v is not a int", trimmedLine)
- }
- event.Retry = tea.Int(retryValue)
- }
- }
- data := strings.TrimRight(tea.StringValue(event.Data), "\n")
- event.Data = tea.String(strings.Trim(data, " "))
- return event, nil
- }
- func getGID() uint64 {
- // https://blog.sgmansfield.com/2015/12/goroutine-ids/
- b := make([]byte, 64)
- b = b[:runtime.Stack(b, false)]
- b = bytes.TrimPrefix(b, []byte("goroutine "))
- b = b[:bytes.IndexByte(b, ' ')]
- n, _ := strconv.ParseUint(string(b), 10, 64)
- return n
- }
- func (s RuntimeOptions) String() string {
- return tea.Prettify(s)
- }
- func (s RuntimeOptions) GoString() string {
- return s.String()
- }
- func (s *RuntimeOptions) SetAutoretry(v bool) *RuntimeOptions {
- s.Autoretry = &v
- return s
- }
- func (s *RuntimeOptions) SetIgnoreSSL(v bool) *RuntimeOptions {
- s.IgnoreSSL = &v
- return s
- }
- func (s *RuntimeOptions) SetKey(v string) *RuntimeOptions {
- s.Key = &v
- return s
- }
- func (s *RuntimeOptions) SetCert(v string) *RuntimeOptions {
- s.Cert = &v
- return s
- }
- func (s *RuntimeOptions) SetCa(v string) *RuntimeOptions {
- s.Ca = &v
- return s
- }
- func (s *RuntimeOptions) SetMaxAttempts(v int) *RuntimeOptions {
- s.MaxAttempts = &v
- return s
- }
- func (s *RuntimeOptions) SetBackoffPolicy(v string) *RuntimeOptions {
- s.BackoffPolicy = &v
- return s
- }
- func (s *RuntimeOptions) SetBackoffPeriod(v int) *RuntimeOptions {
- s.BackoffPeriod = &v
- return s
- }
- func (s *RuntimeOptions) SetReadTimeout(v int) *RuntimeOptions {
- s.ReadTimeout = &v
- return s
- }
- func (s *RuntimeOptions) SetConnectTimeout(v int) *RuntimeOptions {
- s.ConnectTimeout = &v
- return s
- }
- func (s *RuntimeOptions) SetHttpProxy(v string) *RuntimeOptions {
- s.HttpProxy = &v
- return s
- }
- func (s *RuntimeOptions) SetHttpsProxy(v string) *RuntimeOptions {
- s.HttpsProxy = &v
- return s
- }
- func (s *RuntimeOptions) SetNoProxy(v string) *RuntimeOptions {
- s.NoProxy = &v
- return s
- }
- func (s *RuntimeOptions) SetMaxIdleConns(v int) *RuntimeOptions {
- s.MaxIdleConns = &v
- return s
- }
- func (s *RuntimeOptions) SetLocalAddr(v string) *RuntimeOptions {
- s.LocalAddr = &v
- return s
- }
- func (s *RuntimeOptions) SetSocks5Proxy(v string) *RuntimeOptions {
- s.Socks5Proxy = &v
- return s
- }
- func (s *RuntimeOptions) SetSocks5NetWork(v string) *RuntimeOptions {
- s.Socks5NetWork = &v
- return s
- }
- func (s *RuntimeOptions) SetKeepAlive(v bool) *RuntimeOptions {
- s.KeepAlive = &v
- return s
- }
- func (s *RuntimeOptions) SetExtendsParameters(v *ExtendsParameters) *RuntimeOptions {
- s.ExtendsParameters = v
- return s
- }
- func ReadAsString(body io.Reader) (*string, error) {
- byt, err := ioutil.ReadAll(body)
- if err != nil {
- return tea.String(""), err
- }
- r, ok := body.(io.ReadCloser)
- if ok {
- r.Close()
- }
- return tea.String(string(byt)), nil
- }
- func StringifyMapValue(a map[string]interface{}) map[string]*string {
- res := make(map[string]*string)
- for key, value := range a {
- if value != nil {
- res[key] = ToJSONString(value)
- }
- }
- return res
- }
- func AnyifyMapValue(a map[string]*string) map[string]interface{} {
- res := make(map[string]interface{})
- for key, value := range a {
- res[key] = tea.StringValue(value)
- }
- return res
- }
- func ReadAsBytes(body io.Reader) ([]byte, error) {
- byt, err := ioutil.ReadAll(body)
- if err != nil {
- return nil, err
- }
- r, ok := body.(io.ReadCloser)
- if ok {
- r.Close()
- }
- return byt, nil
- }
- func DefaultString(reaStr, defaultStr *string) *string {
- if reaStr == nil {
- return defaultStr
- }
- return reaStr
- }
- func ToJSONString(a interface{}) *string {
- switch v := a.(type) {
- case *string:
- return v
- case string:
- return tea.String(v)
- case []byte:
- return tea.String(string(v))
- case io.Reader:
- byt, err := ioutil.ReadAll(v)
- if err != nil {
- return nil
- }
- return tea.String(string(byt))
- }
- byt := bytes.NewBuffer([]byte{})
- jsonEncoder := json.NewEncoder(byt)
- jsonEncoder.SetEscapeHTML(false)
- if err := jsonEncoder.Encode(a); err != nil {
- return nil
- }
- return tea.String(string(bytes.TrimSpace(byt.Bytes())))
- }
- func DefaultNumber(reaNum, defaultNum *int) *int {
- if reaNum == nil {
- return defaultNum
- }
- return reaNum
- }
- func ReadAsJSON(body io.Reader) (result interface{}, err error) {
- byt, err := ioutil.ReadAll(body)
- if err != nil {
- return
- }
- if string(byt) == "" {
- return
- }
- r, ok := body.(io.ReadCloser)
- if ok {
- r.Close()
- }
- d := json.NewDecoder(bytes.NewReader(byt))
- d.UseNumber()
- err = d.Decode(&result)
- return
- }
- func GetNonce() *string {
- routineId := getGID()
- currentTime := time.Now().UnixNano() / 1e6
- seq := atomic.AddInt64(&seqId, 1)
- randNum := rand.Int63()
- msg := fmt.Sprintf("%d-%d-%d-%d-%d", processStartTime, routineId, currentTime, seq, randNum)
- h := md5.New()
- h.Write([]byte(msg))
- ret := hex.EncodeToString(h.Sum(nil))
- return &ret
- }
- func Empty(val *string) *bool {
- return tea.Bool(val == nil || tea.StringValue(val) == "")
- }
- func ValidateModel(a interface{}) error {
- if a == nil {
- return nil
- }
- err := tea.Validate(a)
- return err
- }
- func EqualString(val1, val2 *string) *bool {
- return tea.Bool(tea.StringValue(val1) == tea.StringValue(val2))
- }
- func EqualNumber(val1, val2 *int) *bool {
- return tea.Bool(tea.IntValue(val1) == tea.IntValue(val2))
- }
- func IsUnset(val interface{}) *bool {
- if val == nil {
- return tea.Bool(true)
- }
- v := reflect.ValueOf(val)
- if v.Kind() == reflect.Ptr || v.Kind() == reflect.Slice || v.Kind() == reflect.Map {
- return tea.Bool(v.IsNil())
- }
- valType := reflect.TypeOf(val)
- valZero := reflect.Zero(valType)
- return tea.Bool(valZero == v)
- }
- func ToBytes(a *string) []byte {
- return []byte(tea.StringValue(a))
- }
- func AssertAsMap(a interface{}) (_result map[string]interface{}, _err error) {
- r := reflect.ValueOf(a)
- if r.Kind().String() != "map" {
- return nil, errors.New(fmt.Sprintf("%v is not a map[string]interface{}", a))
- }
- res := make(map[string]interface{})
- tmp := r.MapKeys()
- for _, key := range tmp {
- res[key.String()] = r.MapIndex(key).Interface()
- }
- return res, nil
- }
- func AssertAsNumber(a interface{}) (_result *int, _err error) {
- res := 0
- switch a.(type) {
- case int:
- tmp := a.(int)
- res = tmp
- case *int:
- tmp := a.(*int)
- res = tea.IntValue(tmp)
- default:
- return nil, errors.New(fmt.Sprintf("%v is not a int", a))
- }
- return tea.Int(res), nil
- }
- /**
- * Assert a value, if it is a integer, return it, otherwise throws
- * @return the integer value
- */
- func AssertAsInteger(value interface{}) (_result *int, _err error) {
- res := 0
- switch value.(type) {
- case int:
- tmp := value.(int)
- res = tmp
- case *int:
- tmp := value.(*int)
- res = tea.IntValue(tmp)
- default:
- return nil, errors.New(fmt.Sprintf("%v is not a int", value))
- }
- return tea.Int(res), nil
- }
- func AssertAsBoolean(a interface{}) (_result *bool, _err error) {
- res := false
- switch a.(type) {
- case bool:
- tmp := a.(bool)
- res = tmp
- case *bool:
- tmp := a.(*bool)
- res = tea.BoolValue(tmp)
- default:
- return nil, errors.New(fmt.Sprintf("%v is not a bool", a))
- }
- return tea.Bool(res), nil
- }
- func AssertAsString(a interface{}) (_result *string, _err error) {
- res := ""
- switch a.(type) {
- case string:
- tmp := a.(string)
- res = tmp
- case *string:
- tmp := a.(*string)
- res = tea.StringValue(tmp)
- default:
- return nil, errors.New(fmt.Sprintf("%v is not a string", a))
- }
- return tea.String(res), nil
- }
- func AssertAsBytes(a interface{}) (_result []byte, _err error) {
- res, ok := a.([]byte)
- if !ok {
- return nil, errors.New(fmt.Sprintf("%v is not a []byte", a))
- }
- return res, nil
- }
- func AssertAsReadable(a interface{}) (_result io.Reader, _err error) {
- res, ok := a.(io.Reader)
- if !ok {
- return nil, errors.New(fmt.Sprintf("%v is not a reader", a))
- }
- return res, nil
- }
- func AssertAsArray(a interface{}) (_result []interface{}, _err error) {
- r := reflect.ValueOf(a)
- if r.Kind().String() != "array" && r.Kind().String() != "slice" {
- return nil, errors.New(fmt.Sprintf("%v is not a []interface{}", a))
- }
- aLen := r.Len()
- res := make([]interface{}, 0)
- for i := 0; i < aLen; i++ {
- res = append(res, r.Index(i).Interface())
- }
- return res, nil
- }
- func ParseJSON(a *string) interface{} {
- mapTmp := make(map[string]interface{})
- d := json.NewDecoder(bytes.NewReader([]byte(tea.StringValue(a))))
- d.UseNumber()
- err := d.Decode(&mapTmp)
- if err == nil {
- return mapTmp
- }
- sliceTmp := make([]interface{}, 0)
- d = json.NewDecoder(bytes.NewReader([]byte(tea.StringValue(a))))
- d.UseNumber()
- err = d.Decode(&sliceTmp)
- if err == nil {
- return sliceTmp
- }
- if num, err := strconv.Atoi(tea.StringValue(a)); err == nil {
- return num
- }
- if ok, err := strconv.ParseBool(tea.StringValue(a)); err == nil {
- return ok
- }
- if floa64tVal, err := strconv.ParseFloat(tea.StringValue(a), 64); err == nil {
- return floa64tVal
- }
- return nil
- }
- func ToString(a []byte) *string {
- return tea.String(string(a))
- }
- func ToMap(in interface{}) map[string]interface{} {
- if in == nil {
- return nil
- }
- res := tea.ToMap(in)
- return res
- }
- func ToFormString(a map[string]interface{}) *string {
- if a == nil {
- return tea.String("")
- }
- res := ""
- urlEncoder := url.Values{}
- for key, value := range a {
- v := fmt.Sprintf("%v", value)
- urlEncoder.Add(key, v)
- }
- res = urlEncoder.Encode()
- return tea.String(res)
- }
- func GetDateUTCString() *string {
- return tea.String(time.Now().UTC().Format(http.TimeFormat))
- }
- func GetUserAgent(userAgent *string) *string {
- if userAgent != nil && tea.StringValue(userAgent) != "" {
- return tea.String(defaultUserAgent + " " + tea.StringValue(userAgent))
- }
- return tea.String(defaultUserAgent)
- }
- func Is2xx(code *int) *bool {
- tmp := tea.IntValue(code)
- return tea.Bool(tmp >= 200 && tmp < 300)
- }
- func Is3xx(code *int) *bool {
- tmp := tea.IntValue(code)
- return tea.Bool(tmp >= 300 && tmp < 400)
- }
- func Is4xx(code *int) *bool {
- tmp := tea.IntValue(code)
- return tea.Bool(tmp >= 400 && tmp < 500)
- }
- func Is5xx(code *int) *bool {
- tmp := tea.IntValue(code)
- return tea.Bool(tmp >= 500 && tmp < 600)
- }
- func Sleep(millisecond *int) error {
- ms := tea.IntValue(millisecond)
- time.Sleep(time.Duration(ms) * time.Millisecond)
- return nil
- }
- func ToArray(in interface{}) []map[string]interface{} {
- if tea.BoolValue(IsUnset(in)) {
- return nil
- }
- tmp := make([]map[string]interface{}, 0)
- byt, _ := json.Marshal(in)
- d := json.NewDecoder(bytes.NewReader(byt))
- d.UseNumber()
- err := d.Decode(&tmp)
- if err != nil {
- return nil
- }
- return tmp
- }
- func ReadAsSSE(body io.ReadCloser) (<-chan SSEEvent, <-chan error) {
- eventChannel := make(chan SSEEvent)
- errorChannel := make(chan error)
- go func() {
- defer body.Close()
- defer close(eventChannel)
- reader := bufio.NewReader(body)
- var eventLines []string
- for {
- line, err := reader.ReadString('\n')
- if err == io.EOF {
- break
- }
- if err != nil {
- errorChannel <- err
- }
- line = strings.TrimRight(line, "\n")
- if line == "" {
- if len(eventLines) > 0 {
- event, err := parseEvent(eventLines)
- if err != nil {
- errorChannel <- err
- }
- eventChannel <- event
- eventLines = []string{}
- }
- continue
- }
- eventLines = append(eventLines, line)
- }
- }()
- return eventChannel, errorChannel
- }
|