client.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package common
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "net/url"
  9. "time"
  10. "github.com/denverdino/aliyungo/util"
  11. )
  12. // A Client represents a client of ECS services
  13. type Client struct {
  14. AccessKeyId string //Access Key Id
  15. AccessKeySecret string //Access Key Secret
  16. debug bool
  17. httpClient *http.Client
  18. endpoint string
  19. version string
  20. }
  21. // NewClient creates a new instance of ECS client
  22. func (client *Client) Init(endpoint, version, accessKeyId, accessKeySecret string) {
  23. client.AccessKeyId = accessKeyId
  24. client.AccessKeySecret = accessKeySecret + "&"
  25. client.debug = false
  26. client.httpClient = &http.Client{}
  27. client.endpoint = endpoint
  28. client.version = version
  29. }
  30. // SetEndpoint sets custom endpoint
  31. func (client *Client) SetEndpoint(endpoint string) {
  32. client.endpoint = endpoint
  33. }
  34. // SetEndpoint sets custom version
  35. func (client *Client) SetVersion(version string) {
  36. client.version = version
  37. }
  38. // SetAccessKeyId sets new AccessKeyId
  39. func (client *Client) SetAccessKeyId(id string) {
  40. client.AccessKeyId = id
  41. }
  42. // SetAccessKeySecret sets new AccessKeySecret
  43. func (client *Client) SetAccessKeySecret(secret string) {
  44. client.AccessKeySecret = secret + "&"
  45. }
  46. // SetDebug sets debug mode to log the request/response message
  47. func (client *Client) SetDebug(debug bool) {
  48. client.debug = debug
  49. }
  50. // Invoke sends the raw HTTP request for ECS services
  51. func (client *Client) Invoke(action string, args interface{}, response interface{}) error {
  52. request := Request{}
  53. request.init(client.version, action, client.AccessKeyId)
  54. query := util.ConvertToQueryValues(request)
  55. util.SetQueryValues(args, &query)
  56. // Sign request
  57. signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret)
  58. // Generate the request URL
  59. requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature)
  60. httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil)
  61. // TODO move to util and add build val flag
  62. httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version)
  63. if err != nil {
  64. return GetClientError(err)
  65. }
  66. t0 := time.Now()
  67. httpResp, err := client.httpClient.Do(httpReq)
  68. t1 := time.Now()
  69. if err != nil {
  70. return GetClientError(err)
  71. }
  72. statusCode := httpResp.StatusCode
  73. if client.debug {
  74. log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0))
  75. }
  76. defer httpResp.Body.Close()
  77. body, err := ioutil.ReadAll(httpResp.Body)
  78. if err != nil {
  79. return GetClientError(err)
  80. }
  81. if client.debug {
  82. var prettyJSON bytes.Buffer
  83. err = json.Indent(&prettyJSON, body, "", " ")
  84. log.Println(string(prettyJSON.Bytes()))
  85. }
  86. if statusCode >= 400 && statusCode <= 599 {
  87. errorResponse := ErrorResponse{}
  88. err = json.Unmarshal(body, &errorResponse)
  89. ecsError := &Error{
  90. ErrorResponse: errorResponse,
  91. StatusCode: statusCode,
  92. }
  93. return ecsError
  94. }
  95. err = json.Unmarshal(body, response)
  96. //log.Printf("%++v", response)
  97. if err != nil {
  98. return GetClientError(err)
  99. }
  100. return nil
  101. }
  102. // GenerateClientToken generates the Client Token with random string
  103. func (client *Client) GenerateClientToken() string {
  104. return util.CreateRandomString()
  105. }
  106. func GetClientErrorFromString(str string) error {
  107. return &Error{
  108. ErrorResponse: ErrorResponse{
  109. Code: "AliyunGoClientFailure",
  110. Message: str,
  111. },
  112. StatusCode: -1,
  113. }
  114. }
  115. func GetClientError(err error) error {
  116. return GetClientErrorFromString(err.Error())
  117. }