146 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
package common
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/json"
 | 
						|
	"io/ioutil"
 | 
						|
	"log"
 | 
						|
	"net/http"
 | 
						|
	"net/url"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/denverdino/aliyungo/util"
 | 
						|
)
 | 
						|
 | 
						|
// A Client represents a client of ECS services
 | 
						|
type Client struct {
 | 
						|
	AccessKeyId     string //Access Key Id
 | 
						|
	AccessKeySecret string //Access Key Secret
 | 
						|
	debug           bool
 | 
						|
	httpClient      *http.Client
 | 
						|
	endpoint        string
 | 
						|
	version         string
 | 
						|
}
 | 
						|
 | 
						|
// NewClient creates a new instance of ECS client
 | 
						|
func (client *Client) Init(endpoint, version, accessKeyId, accessKeySecret string) {
 | 
						|
	client.AccessKeyId = accessKeyId
 | 
						|
	client.AccessKeySecret = accessKeySecret + "&"
 | 
						|
	client.debug = false
 | 
						|
	client.httpClient = &http.Client{}
 | 
						|
	client.endpoint = endpoint
 | 
						|
	client.version = version
 | 
						|
}
 | 
						|
 | 
						|
// SetEndpoint sets custom endpoint
 | 
						|
func (client *Client) SetEndpoint(endpoint string) {
 | 
						|
	client.endpoint = endpoint
 | 
						|
}
 | 
						|
 | 
						|
// SetEndpoint sets custom version
 | 
						|
func (client *Client) SetVersion(version string) {
 | 
						|
	client.version = version
 | 
						|
}
 | 
						|
 | 
						|
// SetAccessKeyId sets new AccessKeyId
 | 
						|
func (client *Client) SetAccessKeyId(id string) {
 | 
						|
	client.AccessKeyId = id
 | 
						|
}
 | 
						|
 | 
						|
// SetAccessKeySecret sets new AccessKeySecret
 | 
						|
func (client *Client) SetAccessKeySecret(secret string) {
 | 
						|
	client.AccessKeySecret = secret + "&"
 | 
						|
}
 | 
						|
 | 
						|
// SetDebug sets debug mode to log the request/response message
 | 
						|
func (client *Client) SetDebug(debug bool) {
 | 
						|
	client.debug = debug
 | 
						|
}
 | 
						|
 | 
						|
// Invoke sends the raw HTTP request for ECS services
 | 
						|
func (client *Client) Invoke(action string, args interface{}, response interface{}) error {
 | 
						|
 | 
						|
	request := Request{}
 | 
						|
	request.init(client.version, action, client.AccessKeyId)
 | 
						|
 | 
						|
	query := util.ConvertToQueryValues(request)
 | 
						|
	util.SetQueryValues(args, &query)
 | 
						|
 | 
						|
	// Sign request
 | 
						|
	signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret)
 | 
						|
 | 
						|
	// Generate the request URL
 | 
						|
	requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature)
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil)
 | 
						|
 | 
						|
	// TODO move to util and add build val flag
 | 
						|
	httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version)
 | 
						|
 | 
						|
	if err != nil {
 | 
						|
		return GetClientError(err)
 | 
						|
	}
 | 
						|
 | 
						|
	t0 := time.Now()
 | 
						|
	httpResp, err := client.httpClient.Do(httpReq)
 | 
						|
	t1 := time.Now()
 | 
						|
	if err != nil {
 | 
						|
		return GetClientError(err)
 | 
						|
	}
 | 
						|
	statusCode := httpResp.StatusCode
 | 
						|
 | 
						|
	if client.debug {
 | 
						|
		log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0))
 | 
						|
	}
 | 
						|
 | 
						|
	defer httpResp.Body.Close()
 | 
						|
	body, err := ioutil.ReadAll(httpResp.Body)
 | 
						|
 | 
						|
	if err != nil {
 | 
						|
		return GetClientError(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if client.debug {
 | 
						|
		var prettyJSON bytes.Buffer
 | 
						|
		err = json.Indent(&prettyJSON, body, "", "    ")
 | 
						|
		log.Println(string(prettyJSON.Bytes()))
 | 
						|
	}
 | 
						|
 | 
						|
	if statusCode >= 400 && statusCode <= 599 {
 | 
						|
		errorResponse := ErrorResponse{}
 | 
						|
		err = json.Unmarshal(body, &errorResponse)
 | 
						|
		ecsError := &Error{
 | 
						|
			ErrorResponse: errorResponse,
 | 
						|
			StatusCode:    statusCode,
 | 
						|
		}
 | 
						|
		return ecsError
 | 
						|
	}
 | 
						|
 | 
						|
	err = json.Unmarshal(body, response)
 | 
						|
	//log.Printf("%++v", response)
 | 
						|
	if err != nil {
 | 
						|
		return GetClientError(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// GenerateClientToken generates the Client Token with random string
 | 
						|
func (client *Client) GenerateClientToken() string {
 | 
						|
	return util.CreateRandomString()
 | 
						|
}
 | 
						|
 | 
						|
func GetClientErrorFromString(str string) error {
 | 
						|
	return &Error{
 | 
						|
		ErrorResponse: ErrorResponse{
 | 
						|
			Code:    "AliyunGoClientFailure",
 | 
						|
			Message: str,
 | 
						|
		},
 | 
						|
		StatusCode: -1,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func GetClientError(err error) error {
 | 
						|
	return GetClientErrorFromString(err.Error())
 | 
						|
}
 |