service.go raw

   1  package service
   2  
   3  import (
   4  	"bufio"
   5  	"bytes"
   6  	"crypto/md5"
   7  	"encoding/hex"
   8  	"encoding/json"
   9  	"errors"
  10  	"fmt"
  11  	"io"
  12  	"io/ioutil"
  13  	"math/rand"
  14  	"net/http"
  15  	"net/url"
  16  	"reflect"
  17  	"runtime"
  18  	"strconv"
  19  	"strings"
  20  	"sync/atomic"
  21  	"time"
  22  
  23  	"github.com/alibabacloud-go/tea/tea"
  24  )
  25  
  26  var defaultUserAgent = fmt.Sprintf("AlibabaCloud (%s; %s) Golang/%s Core/%s TeaDSL/1", runtime.GOOS, runtime.GOARCH, strings.Trim(runtime.Version(), "go"), "0.01")
  27  
  28  type ExtendsParameters struct {
  29  	Headers map[string]*string `json:"headers,omitempty" xml:"headers,omitempty"`
  30  	Queries map[string]*string `json:"queries,omitempty" xml:"queries,omitempty"`
  31  }
  32  
  33  func (s ExtendsParameters) String() string {
  34  	return tea.Prettify(s)
  35  }
  36  
  37  func (s ExtendsParameters) GoString() string {
  38  	return s.String()
  39  }
  40  
  41  func (s *ExtendsParameters) SetHeaders(v map[string]*string) *ExtendsParameters {
  42  	s.Headers = v
  43  	return s
  44  }
  45  
  46  func (s *ExtendsParameters) SetQueries(v map[string]*string) *ExtendsParameters {
  47  	s.Queries = v
  48  	return s
  49  }
  50  
  51  type RuntimeOptions struct {
  52  	Autoretry         *bool              `json:"autoretry" xml:"autoretry"`
  53  	IgnoreSSL         *bool              `json:"ignoreSSL" xml:"ignoreSSL"`
  54  	Key               *string            `json:"key,omitempty" xml:"key,omitempty"`
  55  	Cert              *string            `json:"cert,omitempty" xml:"cert,omitempty"`
  56  	Ca                *string            `json:"ca,omitempty" xml:"ca,omitempty"`
  57  	MaxAttempts       *int               `json:"maxAttempts" xml:"maxAttempts"`
  58  	BackoffPolicy     *string            `json:"backoffPolicy" xml:"backoffPolicy"`
  59  	BackoffPeriod     *int               `json:"backoffPeriod" xml:"backoffPeriod"`
  60  	ReadTimeout       *int               `json:"readTimeout" xml:"readTimeout"`
  61  	ConnectTimeout    *int               `json:"connectTimeout" xml:"connectTimeout"`
  62  	LocalAddr         *string            `json:"localAddr" xml:"localAddr"`
  63  	HttpProxy         *string            `json:"httpProxy" xml:"httpProxy"`
  64  	HttpsProxy        *string            `json:"httpsProxy" xml:"httpsProxy"`
  65  	NoProxy           *string            `json:"noProxy" xml:"noProxy"`
  66  	MaxIdleConns      *int               `json:"maxIdleConns" xml:"maxIdleConns"`
  67  	Socks5Proxy       *string            `json:"socks5Proxy" xml:"socks5Proxy"`
  68  	Socks5NetWork     *string            `json:"socks5NetWork" xml:"socks5NetWork"`
  69  	KeepAlive         *bool              `json:"keepAlive" xml:"keepAlive"`
  70  	ExtendsParameters *ExtendsParameters `json:"extendsParameters,omitempty" xml:"extendsParameters,omitempty"`
  71  }
  72  
  73  var processStartTime int64 = time.Now().UnixNano() / 1e6
  74  var seqId int64 = 0
  75  
  76  type SSEEvent struct {
  77  	ID    *string
  78  	Event *string
  79  	Data  *string
  80  	Retry *int
  81  }
  82  
  83  func parseEvent(eventLines []string) (SSEEvent, error) {
  84  	var event SSEEvent
  85  
  86  	for _, line := range eventLines {
  87  		if strings.HasPrefix(line, "data:") {
  88  			event.Data = tea.String(tea.StringValue(event.Data) + strings.TrimPrefix(line, "data:") + "\n")
  89  		} else if strings.HasPrefix(line, "id:") {
  90  			id := strings.TrimPrefix(line, "id:")
  91  			event.ID = tea.String(strings.Trim(id, " "))
  92  		} else if strings.HasPrefix(line, "event:") {
  93  			eventName := strings.TrimPrefix(line, "event:")
  94  			event.Event = tea.String(strings.Trim(eventName, " "))
  95  		} else if strings.HasPrefix(line, "retry:") {
  96  			trimmedLine := strings.TrimPrefix(line, "retry:")
  97  			trimmedLine = strings.Trim(trimmedLine, " ")
  98  			retryValue, _err := strconv.Atoi(trimmedLine)
  99  			if _err != nil {
 100  				return event, fmt.Errorf("retry %v is not a int", trimmedLine)
 101  			}
 102  			event.Retry = tea.Int(retryValue)
 103  		}
 104  	}
 105  	data := strings.TrimRight(tea.StringValue(event.Data), "\n")
 106  	event.Data = tea.String(strings.Trim(data, " "))
 107  	return event, nil
 108  }
 109  
 110  func getGID() uint64 {
 111  	// https://blog.sgmansfield.com/2015/12/goroutine-ids/
 112  	b := make([]byte, 64)
 113  	b = b[:runtime.Stack(b, false)]
 114  	b = bytes.TrimPrefix(b, []byte("goroutine "))
 115  	b = b[:bytes.IndexByte(b, ' ')]
 116  	n, _ := strconv.ParseUint(string(b), 10, 64)
 117  	return n
 118  }
 119  
 120  func (s RuntimeOptions) String() string {
 121  	return tea.Prettify(s)
 122  }
 123  
 124  func (s RuntimeOptions) GoString() string {
 125  	return s.String()
 126  }
 127  
 128  func (s *RuntimeOptions) SetAutoretry(v bool) *RuntimeOptions {
 129  	s.Autoretry = &v
 130  	return s
 131  }
 132  
 133  func (s *RuntimeOptions) SetIgnoreSSL(v bool) *RuntimeOptions {
 134  	s.IgnoreSSL = &v
 135  	return s
 136  }
 137  
 138  func (s *RuntimeOptions) SetKey(v string) *RuntimeOptions {
 139  	s.Key = &v
 140  	return s
 141  }
 142  
 143  func (s *RuntimeOptions) SetCert(v string) *RuntimeOptions {
 144  	s.Cert = &v
 145  	return s
 146  }
 147  
 148  func (s *RuntimeOptions) SetCa(v string) *RuntimeOptions {
 149  	s.Ca = &v
 150  	return s
 151  }
 152  
 153  func (s *RuntimeOptions) SetMaxAttempts(v int) *RuntimeOptions {
 154  	s.MaxAttempts = &v
 155  	return s
 156  }
 157  
 158  func (s *RuntimeOptions) SetBackoffPolicy(v string) *RuntimeOptions {
 159  	s.BackoffPolicy = &v
 160  	return s
 161  }
 162  
 163  func (s *RuntimeOptions) SetBackoffPeriod(v int) *RuntimeOptions {
 164  	s.BackoffPeriod = &v
 165  	return s
 166  }
 167  
 168  func (s *RuntimeOptions) SetReadTimeout(v int) *RuntimeOptions {
 169  	s.ReadTimeout = &v
 170  	return s
 171  }
 172  
 173  func (s *RuntimeOptions) SetConnectTimeout(v int) *RuntimeOptions {
 174  	s.ConnectTimeout = &v
 175  	return s
 176  }
 177  
 178  func (s *RuntimeOptions) SetHttpProxy(v string) *RuntimeOptions {
 179  	s.HttpProxy = &v
 180  	return s
 181  }
 182  
 183  func (s *RuntimeOptions) SetHttpsProxy(v string) *RuntimeOptions {
 184  	s.HttpsProxy = &v
 185  	return s
 186  }
 187  
 188  func (s *RuntimeOptions) SetNoProxy(v string) *RuntimeOptions {
 189  	s.NoProxy = &v
 190  	return s
 191  }
 192  
 193  func (s *RuntimeOptions) SetMaxIdleConns(v int) *RuntimeOptions {
 194  	s.MaxIdleConns = &v
 195  	return s
 196  }
 197  
 198  func (s *RuntimeOptions) SetLocalAddr(v string) *RuntimeOptions {
 199  	s.LocalAddr = &v
 200  	return s
 201  }
 202  
 203  func (s *RuntimeOptions) SetSocks5Proxy(v string) *RuntimeOptions {
 204  	s.Socks5Proxy = &v
 205  	return s
 206  }
 207  
 208  func (s *RuntimeOptions) SetSocks5NetWork(v string) *RuntimeOptions {
 209  	s.Socks5NetWork = &v
 210  	return s
 211  }
 212  
 213  func (s *RuntimeOptions) SetKeepAlive(v bool) *RuntimeOptions {
 214  	s.KeepAlive = &v
 215  	return s
 216  }
 217  
 218  func (s *RuntimeOptions) SetExtendsParameters(v *ExtendsParameters) *RuntimeOptions {
 219  	s.ExtendsParameters = v
 220  	return s
 221  }
 222  
 223  func ReadAsString(body io.Reader) (*string, error) {
 224  	byt, err := ioutil.ReadAll(body)
 225  	if err != nil {
 226  		return tea.String(""), err
 227  	}
 228  	r, ok := body.(io.ReadCloser)
 229  	if ok {
 230  		r.Close()
 231  	}
 232  	return tea.String(string(byt)), nil
 233  }
 234  
 235  func StringifyMapValue(a map[string]interface{}) map[string]*string {
 236  	res := make(map[string]*string)
 237  	for key, value := range a {
 238  		if value != nil {
 239  			res[key] = ToJSONString(value)
 240  		}
 241  	}
 242  	return res
 243  }
 244  
 245  func AnyifyMapValue(a map[string]*string) map[string]interface{} {
 246  	res := make(map[string]interface{})
 247  	for key, value := range a {
 248  		res[key] = tea.StringValue(value)
 249  	}
 250  	return res
 251  }
 252  
 253  func ReadAsBytes(body io.Reader) ([]byte, error) {
 254  	byt, err := ioutil.ReadAll(body)
 255  	if err != nil {
 256  		return nil, err
 257  	}
 258  	r, ok := body.(io.ReadCloser)
 259  	if ok {
 260  		r.Close()
 261  	}
 262  	return byt, nil
 263  }
 264  
 265  func DefaultString(reaStr, defaultStr *string) *string {
 266  	if reaStr == nil {
 267  		return defaultStr
 268  	}
 269  	return reaStr
 270  }
 271  
 272  func ToJSONString(a interface{}) *string {
 273  	switch v := a.(type) {
 274  	case *string:
 275  		return v
 276  	case string:
 277  		return tea.String(v)
 278  	case []byte:
 279  		return tea.String(string(v))
 280  	case io.Reader:
 281  		byt, err := ioutil.ReadAll(v)
 282  		if err != nil {
 283  			return nil
 284  		}
 285  		return tea.String(string(byt))
 286  	}
 287  	byt := bytes.NewBuffer([]byte{})
 288  	jsonEncoder := json.NewEncoder(byt)
 289  	jsonEncoder.SetEscapeHTML(false)
 290  	if err := jsonEncoder.Encode(a); err != nil {
 291  		return nil
 292  	}
 293  	return tea.String(string(bytes.TrimSpace(byt.Bytes())))
 294  }
 295  
 296  func DefaultNumber(reaNum, defaultNum *int) *int {
 297  	if reaNum == nil {
 298  		return defaultNum
 299  	}
 300  	return reaNum
 301  }
 302  
 303  func ReadAsJSON(body io.Reader) (result interface{}, err error) {
 304  	byt, err := ioutil.ReadAll(body)
 305  	if err != nil {
 306  		return
 307  	}
 308  	if string(byt) == "" {
 309  		return
 310  	}
 311  	r, ok := body.(io.ReadCloser)
 312  	if ok {
 313  		r.Close()
 314  	}
 315  	d := json.NewDecoder(bytes.NewReader(byt))
 316  	d.UseNumber()
 317  	err = d.Decode(&result)
 318  	return
 319  }
 320  
 321  func GetNonce() *string {
 322  	routineId := getGID()
 323  	currentTime := time.Now().UnixNano() / 1e6
 324  	seq := atomic.AddInt64(&seqId, 1)
 325  	randNum := rand.Int63()
 326  	msg := fmt.Sprintf("%d-%d-%d-%d-%d", processStartTime, routineId, currentTime, seq, randNum)
 327  	h := md5.New()
 328  	h.Write([]byte(msg))
 329  	ret := hex.EncodeToString(h.Sum(nil))
 330  	return &ret
 331  }
 332  
 333  func Empty(val *string) *bool {
 334  	return tea.Bool(val == nil || tea.StringValue(val) == "")
 335  }
 336  
 337  func ValidateModel(a interface{}) error {
 338  	if a == nil {
 339  		return nil
 340  	}
 341  	err := tea.Validate(a)
 342  	return err
 343  }
 344  
 345  func EqualString(val1, val2 *string) *bool {
 346  	return tea.Bool(tea.StringValue(val1) == tea.StringValue(val2))
 347  }
 348  
 349  func EqualNumber(val1, val2 *int) *bool {
 350  	return tea.Bool(tea.IntValue(val1) == tea.IntValue(val2))
 351  }
 352  
 353  func IsUnset(val interface{}) *bool {
 354  	if val == nil {
 355  		return tea.Bool(true)
 356  	}
 357  
 358  	v := reflect.ValueOf(val)
 359  	if v.Kind() == reflect.Ptr || v.Kind() == reflect.Slice || v.Kind() == reflect.Map {
 360  		return tea.Bool(v.IsNil())
 361  	}
 362  
 363  	valType := reflect.TypeOf(val)
 364  	valZero := reflect.Zero(valType)
 365  	return tea.Bool(valZero == v)
 366  }
 367  
 368  func ToBytes(a *string) []byte {
 369  	return []byte(tea.StringValue(a))
 370  }
 371  
 372  func AssertAsMap(a interface{}) (_result map[string]interface{}, _err error) {
 373  	r := reflect.ValueOf(a)
 374  	if r.Kind().String() != "map" {
 375  		return nil, errors.New(fmt.Sprintf("%v is not a map[string]interface{}", a))
 376  	}
 377  
 378  	res := make(map[string]interface{})
 379  	tmp := r.MapKeys()
 380  	for _, key := range tmp {
 381  		res[key.String()] = r.MapIndex(key).Interface()
 382  	}
 383  
 384  	return res, nil
 385  }
 386  
 387  func AssertAsNumber(a interface{}) (_result *int, _err error) {
 388  	res := 0
 389  	switch a.(type) {
 390  	case int:
 391  		tmp := a.(int)
 392  		res = tmp
 393  	case *int:
 394  		tmp := a.(*int)
 395  		res = tea.IntValue(tmp)
 396  	default:
 397  		return nil, errors.New(fmt.Sprintf("%v is not a int", a))
 398  	}
 399  
 400  	return tea.Int(res), nil
 401  }
 402  
 403  /**
 404   * Assert a value, if it is a integer, return it, otherwise throws
 405   * @return the integer value
 406   */
 407  func AssertAsInteger(value interface{}) (_result *int, _err error) {
 408  	res := 0
 409  	switch value.(type) {
 410  	case int:
 411  		tmp := value.(int)
 412  		res = tmp
 413  	case *int:
 414  		tmp := value.(*int)
 415  		res = tea.IntValue(tmp)
 416  	default:
 417  		return nil, errors.New(fmt.Sprintf("%v is not a int", value))
 418  	}
 419  
 420  	return tea.Int(res), nil
 421  }
 422  
 423  func AssertAsBoolean(a interface{}) (_result *bool, _err error) {
 424  	res := false
 425  	switch a.(type) {
 426  	case bool:
 427  		tmp := a.(bool)
 428  		res = tmp
 429  	case *bool:
 430  		tmp := a.(*bool)
 431  		res = tea.BoolValue(tmp)
 432  	default:
 433  		return nil, errors.New(fmt.Sprintf("%v is not a bool", a))
 434  	}
 435  
 436  	return tea.Bool(res), nil
 437  }
 438  
 439  func AssertAsString(a interface{}) (_result *string, _err error) {
 440  	res := ""
 441  	switch a.(type) {
 442  	case string:
 443  		tmp := a.(string)
 444  		res = tmp
 445  	case *string:
 446  		tmp := a.(*string)
 447  		res = tea.StringValue(tmp)
 448  	default:
 449  		return nil, errors.New(fmt.Sprintf("%v is not a string", a))
 450  	}
 451  
 452  	return tea.String(res), nil
 453  }
 454  
 455  func AssertAsBytes(a interface{}) (_result []byte, _err error) {
 456  	res, ok := a.([]byte)
 457  	if !ok {
 458  		return nil, errors.New(fmt.Sprintf("%v is not a []byte", a))
 459  	}
 460  	return res, nil
 461  }
 462  
 463  func AssertAsReadable(a interface{}) (_result io.Reader, _err error) {
 464  	res, ok := a.(io.Reader)
 465  	if !ok {
 466  		return nil, errors.New(fmt.Sprintf("%v is not a reader", a))
 467  	}
 468  	return res, nil
 469  }
 470  
 471  func AssertAsArray(a interface{}) (_result []interface{}, _err error) {
 472  	r := reflect.ValueOf(a)
 473  	if r.Kind().String() != "array" && r.Kind().String() != "slice" {
 474  		return nil, errors.New(fmt.Sprintf("%v is not a []interface{}", a))
 475  	}
 476  	aLen := r.Len()
 477  	res := make([]interface{}, 0)
 478  	for i := 0; i < aLen; i++ {
 479  		res = append(res, r.Index(i).Interface())
 480  	}
 481  	return res, nil
 482  }
 483  
 484  func ParseJSON(a *string) interface{} {
 485  	mapTmp := make(map[string]interface{})
 486  	d := json.NewDecoder(bytes.NewReader([]byte(tea.StringValue(a))))
 487  	d.UseNumber()
 488  	err := d.Decode(&mapTmp)
 489  	if err == nil {
 490  		return mapTmp
 491  	}
 492  
 493  	sliceTmp := make([]interface{}, 0)
 494  	d = json.NewDecoder(bytes.NewReader([]byte(tea.StringValue(a))))
 495  	d.UseNumber()
 496  	err = d.Decode(&sliceTmp)
 497  	if err == nil {
 498  		return sliceTmp
 499  	}
 500  
 501  	if num, err := strconv.Atoi(tea.StringValue(a)); err == nil {
 502  		return num
 503  	}
 504  
 505  	if ok, err := strconv.ParseBool(tea.StringValue(a)); err == nil {
 506  		return ok
 507  	}
 508  
 509  	if floa64tVal, err := strconv.ParseFloat(tea.StringValue(a), 64); err == nil {
 510  		return floa64tVal
 511  	}
 512  	return nil
 513  }
 514  
 515  func ToString(a []byte) *string {
 516  	return tea.String(string(a))
 517  }
 518  
 519  func ToMap(in interface{}) map[string]interface{} {
 520  	if in == nil {
 521  		return nil
 522  	}
 523  	res := tea.ToMap(in)
 524  	return res
 525  }
 526  
 527  func ToFormString(a map[string]interface{}) *string {
 528  	if a == nil {
 529  		return tea.String("")
 530  	}
 531  	res := ""
 532  	urlEncoder := url.Values{}
 533  	for key, value := range a {
 534  		v := fmt.Sprintf("%v", value)
 535  		urlEncoder.Add(key, v)
 536  	}
 537  	res = urlEncoder.Encode()
 538  	return tea.String(res)
 539  }
 540  
 541  func GetDateUTCString() *string {
 542  	return tea.String(time.Now().UTC().Format(http.TimeFormat))
 543  }
 544  
 545  func GetUserAgent(userAgent *string) *string {
 546  	if userAgent != nil && tea.StringValue(userAgent) != "" {
 547  		return tea.String(defaultUserAgent + " " + tea.StringValue(userAgent))
 548  	}
 549  	return tea.String(defaultUserAgent)
 550  }
 551  
 552  func Is2xx(code *int) *bool {
 553  	tmp := tea.IntValue(code)
 554  	return tea.Bool(tmp >= 200 && tmp < 300)
 555  }
 556  
 557  func Is3xx(code *int) *bool {
 558  	tmp := tea.IntValue(code)
 559  	return tea.Bool(tmp >= 300 && tmp < 400)
 560  }
 561  
 562  func Is4xx(code *int) *bool {
 563  	tmp := tea.IntValue(code)
 564  	return tea.Bool(tmp >= 400 && tmp < 500)
 565  }
 566  
 567  func Is5xx(code *int) *bool {
 568  	tmp := tea.IntValue(code)
 569  	return tea.Bool(tmp >= 500 && tmp < 600)
 570  }
 571  
 572  func Sleep(millisecond *int) error {
 573  	ms := tea.IntValue(millisecond)
 574  	time.Sleep(time.Duration(ms) * time.Millisecond)
 575  	return nil
 576  }
 577  
 578  func ToArray(in interface{}) []map[string]interface{} {
 579  	if tea.BoolValue(IsUnset(in)) {
 580  		return nil
 581  	}
 582  
 583  	tmp := make([]map[string]interface{}, 0)
 584  	byt, _ := json.Marshal(in)
 585  	d := json.NewDecoder(bytes.NewReader(byt))
 586  	d.UseNumber()
 587  	err := d.Decode(&tmp)
 588  	if err != nil {
 589  		return nil
 590  	}
 591  	return tmp
 592  }
 593  
 594  func ReadAsSSE(body io.ReadCloser) (<-chan SSEEvent, <-chan error) {
 595  	eventChannel := make(chan SSEEvent)
 596  	errorChannel := make(chan error)
 597  
 598  	go func() {
 599  		defer body.Close()
 600  		defer close(eventChannel)
 601  
 602  		reader := bufio.NewReader(body)
 603  		var eventLines []string
 604  
 605  		for {
 606  			line, err := reader.ReadString('\n')
 607  			if err == io.EOF {
 608  				break
 609  			}
 610  			if err != nil {
 611  				errorChannel <- err
 612  			}
 613  
 614  			line = strings.TrimRight(line, "\n")
 615  			if line == "" {
 616  				if len(eventLines) > 0 {
 617  					event, err := parseEvent(eventLines)
 618  					if err != nil {
 619  						errorChannel <- err
 620  					}
 621  					eventChannel <- event
 622  					eventLines = []string{}
 623  				}
 624  				continue
 625  			}
 626  			eventLines = append(eventLines, line)
 627  		}
 628  	}()
 629  	return eventChannel, errorChannel
 630  }
 631