diff --git a/sdk/auth/credentials/access_key_creditial.go b/sdk/auth/credentials/access_key_creditial.go new file mode 100644 index 0000000..8230ae7 --- /dev/null +++ b/sdk/auth/credentials/access_key_creditial.go @@ -0,0 +1,11 @@ +package credentials + +type BaseCredential struct { + AccessKeyId string + AccessKeySecret string +} + +type AccessKeyCredential struct { + AccessKeyId string + AccessKeySecret string +} diff --git a/sdk/auth/crediantial.go b/sdk/auth/crediantial.go index d07f45f..29338e7 100644 --- a/sdk/auth/crediantial.go +++ b/sdk/auth/crediantial.go @@ -1,6 +1,4 @@ package auth -type Creditial struct { - AccessKeyId string - AccessKeySecret string +type Credential interface { } diff --git a/sdk/auth/http_build_param.go b/sdk/auth/http_build_param.go new file mode 100644 index 0000000..c331384 --- /dev/null +++ b/sdk/auth/http_build_param.go @@ -0,0 +1,28 @@ +package auth + +import ( + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/utils" + "net/url" + "strings" +) + +func buildRpcStringToSign(request requests.AcsRequest) (stringToSign string) { + signParams := make(map[string]string) + for key, value := range request.GetQueryParams() { + signParams[key] = value + } + for key, value := range request.GetFormParams() { + signParams[key] = value + } + + stringToSign = utils.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 = request.GetMethod() + "&%2F&" + stringToSign + return +} + + diff --git a/sdk/auth/signer.go b/sdk/auth/signer.go new file mode 100644 index 0000000..5c7f331 --- /dev/null +++ b/sdk/auth/signer.go @@ -0,0 +1,32 @@ +package auth + +import ( + "errors" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/credentials" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/signers" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses" +) + +type Signer interface { + GetName() string + Sign(stringToSign, secretSuffix string) string +} + + +func NewSignerWithCredential(credential Credential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer Signer, err error) { + switch instance := credential.(type) { + case *credentials.AccessKeyCredential: + signer = signers.NewAccessKeySigner(instance) + default: + err = errors.New("UnsupportedCredentialErrorCode = SDK.UnsupportedCredential") + } + return +} + + + +func Sign(request requests.AcsRequest, signer Signer, regionId string) (err error) { + + +} \ No newline at end of file diff --git a/sdk/auth/signers/access_key_siginer.go b/sdk/auth/signers/access_key_siginer.go new file mode 100644 index 0000000..25805a1 --- /dev/null +++ b/sdk/auth/signers/access_key_siginer.go @@ -0,0 +1,41 @@ +package signers + +import ( + "crypto/hmac" + "crypto/sha1" + "encoding/base64" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/credentials" +) + +type AccessKeySigner struct { + credential *credentials.AccessKeyCredential +} + +func NewAccessKeySigner(credential *credentials.AccessKeyCredential) *AccessKeySigner { + return &AccessKeySigner{ + credential: credential, + } +} + + +func (*AccessKeySigner) GetName() string { + return "HMAC-SHA1" +} + + +func (signer *AccessKeySigner) Sign(stringToSign, secretSuffix string) string { + secret := signer.credential.AccessKeySecret + secretSuffix + return ShaHmac1(stringToSign, secret) +} + + +func ShaHmac1(source, secret string) string { + key := []byte(secret) + hmac := hmac.New(sha1.New, key) + hmac.Write([]byte(source)) + signedBytes := hmac.Sum(nil) + signedString := base64.StdEncoding.EncodeToString(signedBytes) + return signedString +} + + diff --git a/sdk/client.go b/sdk/client.go index 6372ca7..043cfaf 100644 --- a/sdk/client.go +++ b/sdk/client.go @@ -4,8 +4,8 @@ import ( "context" "fmt" "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth" - "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/request" - "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/response" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests" + "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses" "net" "net/http" "runtime" @@ -22,13 +22,13 @@ type Client struct { Host string httpClient *http.Client isInsecure bool - signer *auth.Creditial + signer auth.Signer readTimeout time.Duration connectTimeout time.Duration config *Config } -func (client *Client) InitWithOptions(host string, config *Config, creditial auth.Creditial) (err error) { +func (client *Client) InitWithOptions(host string, config *Config, creditial auth.Credential) (err error) { client.httpClient = &http.Client{} if config.Transport != nil { @@ -41,6 +41,9 @@ func (client *Client) InitWithOptions(host string, config *Config, creditial aut client.httpClient.Timeout = config.Timeout } + + client.signer, err = auth.NewSignerWithCredential(credential, client.ProcessCommonRequestWithSigner) + return nil } @@ -52,6 +55,16 @@ func (client *Client) InitWithConfig() (config *Config) { } } + +func (client *Client) ProcessCommonRequestWithSigner(request *requests.CommonRequest, signerInterface interface{}) (response *responses.CommonResponse, err error) { + if signer, isSigner := signerInterface.(auth.Signer); isSigner { + response = responses.NewCommonResponse() + err = client.DoActionWithSigner(request, response, signer) + return + } + panic("should not be here") +} + func Timeout(connectTimeout time.Duration) func(ctx context.Context, net, addr string) (c net.Conn, err error) { return func(ctx context.Context, network, address string) (c net.Conn, err error) { return (&net.Dialer{ @@ -61,7 +74,7 @@ func Timeout(connectTimeout time.Duration) func(ctx context.Context, net, addr s } } -func (client *Client) setTimeOut(request request.AcsRequest) { +func (client *Client) setTimeOut(request requests.AcsRequest) { readTimeout, connectTimeout := client.getTimeOut(request) client.httpClient.Timeout = readTimeout if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil { @@ -74,7 +87,7 @@ func (client *Client) setTimeOut(request request.AcsRequest) { } } -func (client *Client) getTimeOut(request request.AcsRequest) (time.Duration, time.Duration) { +func (client *Client) getTimeOut(request requests.AcsRequest) (time.Duration, time.Duration) { readTimeOut := defaultReadTimeout connectTimeOut := defaultConnectTimeout @@ -96,6 +109,10 @@ func (client *Client) getTimeOut(request request.AcsRequest) (time.Duration, tim return readTimeOut, connectTimeOut } -func (client *Client) DoAction(request request.AcsRequest, response response.AcsResponse) (err error) { +func (client *Client) DoAction(request requests.AcsRequest, response responses.AcsResponse) (err error) { + return client.DoActionWithSigner(request, response, nil) +} + +func (client *Client) DoActionWithSigner(request requests.AcsRequest, response responses.AcsResponse, signer auth.Signer) (err error) { return nil } diff --git a/sdk/request/request.go b/sdk/request/request.go deleted file mode 100644 index fb27e06..0000000 --- a/sdk/request/request.go +++ /dev/null @@ -1,17 +0,0 @@ -package request - -import "time" - -type AcsRequest interface { - GetReadTimeout() time.Duration - GetConnectTimeout() time.Duration - SetReadTimeout(readTimeOut time.Duration) - SetConnectTimeout(connectTimeOut time.Duration) -} - -type baseRequest struct { - Scheme string - Method string - Host string - Domain string -} diff --git a/sdk/request/rpc_request.go b/sdk/request/rpc_request.go deleted file mode 100644 index c1464d5..0000000 --- a/sdk/request/rpc_request.go +++ /dev/null @@ -1,5 +0,0 @@ -package request - -type RpcRequest struct { - *baseRequest -} diff --git a/sdk/requests/common_request.go b/sdk/requests/common_request.go new file mode 100644 index 0000000..f442971 --- /dev/null +++ b/sdk/requests/common_request.go @@ -0,0 +1,5 @@ +package requests + +type CommonRequest struct { + *baseRequest +} diff --git a/sdk/requests/http_request.go b/sdk/requests/http_request.go new file mode 100644 index 0000000..53c93a6 --- /dev/null +++ b/sdk/requests/http_request.go @@ -0,0 +1,5 @@ +package requests + +type HttpRequest struct { + *baseRequest +} diff --git a/sdk/requests/request.go b/sdk/requests/request.go new file mode 100644 index 0000000..f720067 --- /dev/null +++ b/sdk/requests/request.go @@ -0,0 +1,129 @@ +package requests + +import ( + "time" +) + +const ( + RPC = "RPC" + ROA = "ROA" + + HTTP = "HTTP" + HTTPS = "HTTPS" + + DefaultHttpPort = "80" + + GET = "GET" + PUT = "PUT" + POST = "POST" + DELETE = "DELETE" + PATCH = "PATCH" + HEAD = "HEAD" + OPTIONS = "OPTIONS" + + Json = "application/json" + Xml = "application/xml" + Raw = "application/octet-stream" + Form = "application/x-www-form-urlencoded" + + Header = "Header" + Query = "Query" + Body = "Body" + Path = "Path" + + HeaderSeparator = "\n" +) + +type AcsRequest interface { + GetReadTimeout() time.Duration + GetConnectTimeout() time.Duration + SetReadTimeout(readTimeOut time.Duration) + SetConnectTimeout(connectTimeOut time.Duration) + SetHTTPSInsecure(isInsecure bool) + GetHTTPSInsecure() *bool + GetQueryParams() map[string]string + GetFormParams() map[string]string + GetMethod() string + SetStringToSign(stringToSign string) +} + +type baseRequest struct { + Scheme string + Method string + Host string + Domain string + From string + ReadTimeout time.Duration + ConnectTimeout time.Duration + isInsecure *bool + + AcceptFormat string + + userAgent map[string]string + product string + version string + + QueryParams map[string]string + Headers map[string]string + FormParams map[string]string + Content []byte + + queries string + stringToSign string +} + +func (request *baseRequest) GetMethod() string { + return request.Method +} + +func (request *baseRequest) GetFormParams() map[string]string { + return request.FormParams +} + +func (request *baseRequest) GetQueryParams() map[string]string { + return request.QueryParams +} + +func (request *baseRequest) SetHTTPSInsecure(isInsecure bool) { + request.isInsecure = &isInsecure +} + +func (request *baseRequest) GetHTTPSInsecure() *bool { + return request.isInsecure +} + +func (request *baseRequest) GetReadTimeout() time.Duration { + return request.ReadTimeout +} + +func (request *baseRequest) GetConnectTimeout() time.Duration { + return request.ConnectTimeout +} + +func (request *baseRequest) SetReadTimeout(readTimeOut time.Duration) { + request.ReadTimeout = readTimeOut +} + +func (request *baseRequest) SetConnectTimeout(connectTimeOut time.Duration) { + request.ConnectTimeout = connectTimeOut +} + +func (request *baseRequest) SetStringToSign(stringToSign string) { + request.stringToSign = stringToSign +} + +func defaultBaseRequest() (request *baseRequest) { + request = &baseRequest{ + Scheme: "", + AcceptFormat: "JSON", + Method: GET, + QueryParams: make(map[string]string), + Headers: map[string]string{ + "x-sdk-client": "golang/1.0.0", + "x-sdk-invoke-type": "normal", + "Accept-Encoding": "identity", + }, + FormParams: make(map[string]string), + } + return +} diff --git a/sdk/response/response.go b/sdk/response/response.go deleted file mode 100644 index 25c14ba..0000000 --- a/sdk/response/response.go +++ /dev/null @@ -1,4 +0,0 @@ -package response - -type AcsResponse interface { -} diff --git a/sdk/responses/response.go b/sdk/responses/response.go new file mode 100644 index 0000000..d94d18b --- /dev/null +++ b/sdk/responses/response.go @@ -0,0 +1,75 @@ +package responses + +import ( + "io/ioutil" + "net/http" +) + +type AcsResponse interface { + IsSuccess() bool + GetHttpStatus() int + GetHttpHeaders() map[string][]string + GetHttpContentString() string + GetHttpContentBytes() []byte + GetOriginHttpResponse() *http.Response + parseFromHttpResponse(httpResponse *http.Response) error +} + +type BaseResponse struct { + httpStatus int + httpHeaders map[string][]string + httpContentString string + httpContentBytes []byte + originHttpResponse *http.Response +} + +func (baseResponse *BaseResponse) GetHttpStatus() int { + return baseResponse.httpStatus +} + +func (baseResponse *BaseResponse) GetHttpHeaders() map[string][]string { + return baseResponse.httpHeaders +} + +func (baseResponse *BaseResponse) GetHttpContentString() string { + return baseResponse.httpContentString +} + +func (baseResponse *BaseResponse) GetHttpContentBytes() []byte { + return baseResponse.httpContentBytes +} + +func (baseResponse *BaseResponse) GetOriginHttpResponse() *http.Response { + return baseResponse.originHttpResponse +} + +func (baseResponse *BaseResponse) IsSuccess() bool { + if baseResponse.GetHttpStatus() >= 200 && baseResponse.GetHttpStatus() < 300 { + return true + } + return false +} + +func (baseResponse *BaseResponse) parseFromHttpResponse(httpResponse *http.Response) (err error) { + defer httpResponse.Body.Close() + body, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + baseResponse.httpStatus = httpResponse.StatusCode + baseResponse.httpHeaders = httpResponse.Header + baseResponse.httpContentBytes = body + baseResponse.httpContentString = string(body) + baseResponse.originHttpResponse = httpResponse + return +} + +type CommonResponse struct { + *BaseResponse +} + +func NewCommonResponse() (response *CommonResponse) { + return &CommonResponse{ + BaseResponse: &BaseResponse{}, + } +} diff --git a/sdk/utils/utils.go b/sdk/utils/utils.go new file mode 100644 index 0000000..824ef58 --- /dev/null +++ b/sdk/utils/utils.go @@ -0,0 +1,12 @@ +package utils + +import "net/url" + +func GetUrlFormedMap(source map[string]string) (urlEncoded string) { + urlEncoder := url.Values{} + for key, value := range source { + urlEncoder.Add(key, value) + } + urlEncoded = urlEncoder.Encode() + return +}