|
- package sdk
-
- import (
- "bytes"
- "context"
- "crypto/tls"
- "fmt"
- "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth"
- "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/credentials"
- "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
- "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses"
- "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/utils"
- "net"
- "net/http"
- "net/http/httputil"
- "net/url"
- "os"
- "regexp"
- "runtime"
- "strings"
- "time"
- )
-
- var Version = "0.0.1"
- var defaultConnectTimeout = 5 * time.Second
- var defaultReadTimeout = 10 * time.Second
- var defaultDomain = ".gaore.com"
- var DefaultUserAgent = fmt.Sprintf("GaoreGoSdk (%s;%s) Golang/%s Core/%s", runtime.GOOS, runtime.GOARCH, strings.Trim(runtime.Version(), "go"), Version)
-
- var debug utils.Debug
-
- func init() {
- debug = utils.Init("sdk")
- }
-
- type Client struct {
- Host string
- httpClient *http.Client
- isInsecure bool
- signer auth.Signer
- readTimeout time.Duration
- connectTimeout time.Duration
- config *Config
- httpProxy string
- httpsProxy string
- noProxy string
- }
-
- func (client *Client) GetNoProxy() string {
- return client.noProxy
- }
-
- func (client *Client) SetNoProxy(noProxy string) {
- client.noProxy = noProxy
- }
-
- func (client *Client) GetHttpsProxy() string {
- return client.httpsProxy
- }
-
- func (client *Client) SetHttpsProxy(httpsProxy string) {
- client.httpsProxy = httpsProxy
- }
-
- func (client *Client) SetHttpProxy(httpProxy string) {
- client.httpProxy = httpProxy
- }
-
- func (client *Client) GetHttpProxy() string {
- return client.httpProxy
- }
-
- func (client *Client) GetHTTPSInsecure() bool {
- return client.isInsecure
- }
-
- func (client *Client) InitClientConfig() (config *Config) {
- if client.config != nil {
- return client.config
- } else {
- return NewConfig()
- }
-
- }
-
- func (client *Client) InitWithAccessKey(accessKeyId, accessKeySecret, accessKeyFrom string) (err error) {
- config := client.InitWithConfig()
- credential := &credentials.BaseCredential{
- AccessKeyId: accessKeyId,
- AccessKeySecret: accessKeySecret,
- AccessKeyFrom: accessKeyFrom,
- }
- return client.InitWithOptions(config, credential)
- }
-
- func (client *Client) InitWithAliAppcode(accessKeyId, accessKeySecret string, env ...string) (err error) {
- config := client.InitWithConfig()
- credential := credentials.NewAliAppcodeCredential(accessKeyId, accessKeySecret)
-
- if len(env) > 0 {
- config.Env = env[0]
- }
-
- return client.InitWithOptions(config, credential)
- }
-
- func (client *Client) InitWithStsToken(accessKeyId, accessKeySecret, accessKeyFrom string) (err error) {
- config := client.InitWithConfig()
- credential := &credentials.StdTokenCredential{
- AccessKeyId: accessKeyId,
- AccessKeySecret: accessKeySecret,
- AccessKeyFrom: accessKeyFrom,
- }
- return client.InitWithOptions(config, credential)
- }
-
- func (client *Client) InitWithOptions(config *Config, credential auth.Credential) (err error) {
- client.httpClient = &http.Client{}
- client.config = config
-
- if config.Transport != nil {
- client.httpClient.Transport = config.Transport
- } else if config.HttpTransport != nil {
- client.httpClient.Transport = config.HttpTransport
- }
-
- if config.Timeout > 0 {
- client.httpClient.Timeout = config.Timeout
- }
-
- client.signer, err = auth.NewSignerWithCredential(credential, client.ProcessCommonRequestWithSigner)
- return
- }
-
- func (client *Client) InitWithConfig() (config *Config) {
- if client.config != nil {
- return client.config
- } else {
- return NewConfig()
- }
- }
-
- 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{
- Timeout: connectTimeout,
- DualStack: true,
- }).DialContext(ctx, network, address)
- }
- }
-
- 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 {
- trans.DialContext = Timeout(connectTimeout)
- client.httpClient.Transport = trans
- } else if client.httpClient.Transport == nil {
- client.httpClient.Transport = &http.Transport{
- DialContext: Timeout(connectTimeout),
- }
- }
- }
-
- func (client *Client) getTimeOut(request requests.AcsRequest) (time.Duration, time.Duration) {
- readTimeOut := defaultReadTimeout
- connectTimeOut := defaultConnectTimeout
-
- reqReadTimeout := request.GetReadTimeout()
- reqConnectTimeout := request.GetConnectTimeout()
- if reqReadTimeout != 0*time.Millisecond {
- readTimeOut = reqReadTimeout
- } else if client.readTimeout != 0*time.Microsecond {
- readTimeOut = client.readTimeout
- } else if client.httpClient.Timeout != 0 {
- readTimeOut = client.httpClient.Timeout
- }
-
- if reqConnectTimeout != 0*time.Microsecond {
- connectTimeOut = reqConnectTimeout
- } else if client.connectTimeout != 0*time.Millisecond {
- connectTimeOut = client.connectTimeout
- }
- return readTimeOut, connectTimeOut
- }
-
- func (client *Client) getHTTPSInsecure(request requests.AcsRequest) (insecure bool) {
- if request.GetHTTPSInsecure() != nil {
- insecure = *request.GetHTTPSInsecure()
- } else {
- insecure = client.GetHTTPSInsecure()
- }
- return
- }
-
- 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) {
-
- httpRequest, err := client.buildRequestWithSigner(request, signer)
- if err != nil {
- return err
- }
-
- client.setTimeOut(request)
- proxy, err := client.getHttpProxy(httpRequest.URL.Scheme)
- if err != nil {
- return err
- }
- noProxy := client.getNoProxy(httpRequest.URL.Scheme)
- var flag bool
- for _, value := range noProxy {
- if strings.HasPrefix(value, "*") {
- value = fmt.Sprint(".%s", value)
- }
- noProxyReg, err := regexp.Compile(value)
- if err != nil {
- return err
- }
- if noProxyReg.MatchString(httpRequest.Host) {
- flag = true
- break
- }
- }
-
- if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil {
- if trans.TLSClientConfig != nil {
- trans.TLSClientConfig.InsecureSkipVerify = client.getHTTPSInsecure(request)
- } else {
- trans.TLSClientConfig = &tls.Config{
- InsecureSkipVerify: client.getHTTPSInsecure(request),
- }
- }
-
- if proxy != nil && !flag {
- trans.Proxy = http.ProxyURL(proxy)
- }
-
- client.httpClient.Transport = trans
- }
-
- dump, err := httputil.DumpRequest(httpRequest, true)
- debug("client %s", bytes.NewBuffer(dump).String())
-
- var httpResponse *http.Response
- httpResponse, err = hookDo(client.httpClient.Do)(httpRequest)
- if err != nil {
- return
- }
-
- err = responses.Unmarshal(response, httpResponse, request.GetAcceptFormat())
- return
- }
-
- func (client *Client) buildRequestWithSigner(request requests.AcsRequest, signer auth.Signer) (httpRequest *http.Request, err error) {
- // init param
- domain := request.GetDomain()
- if strings.Index(domain.Default, ".") < 0 {
- domain.Default += defaultDomain
- request.SetDomain(domain)
- }
-
- if request.GetScheme() == "" {
- request.SetScheme(client.config.Scheme)
- }
-
- if request.GetEnv() == "" && client.config.Env != "" {
- request.SetEnv(client.config.Env)
- }
-
- err = requests.InitParam(request)
- if err != nil {
- return
- }
- // build signature
- var finalSigner auth.Signer
- if signer != nil {
- finalSigner = signer
- } else {
- finalSigner = client.signer
- }
- err = auth.Sign(request, finalSigner)
- if err != nil {
- return
- }
-
- // build request
- requestMethod := request.GetMethod()
- requestUrl := request.BuildUrl()
- body := request.GetBodyReader()
- httpRequest, err = http.NewRequest(requestMethod, requestUrl, body)
- if err != nil {
- return
- }
-
- for key, val := range request.GetHeaders() {
- httpRequest.Header[key] = []string{val}
- }
-
- if host, isContainsHost := request.GetHeaders()["host"]; isContainsHost {
- httpRequest.Host = host
- }
-
- userAgent := DefaultUserAgent
- httpRequest.Header.Set("User-Agent", userAgent)
-
- return
- }
-
- func (client *Client) getHttpProxy(scheme string) (proxy *url.URL, err error) {
- switch scheme {
- case "https":
- if client.GetHttpsProxy() != "" {
- proxy, err = url.Parse(client.httpsProxy)
- } else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
- proxy, err = url.Parse(rawurl)
- } else if rawurl := os.Getenv("https_proxy"); rawurl != "" {
- proxy, err = url.Parse(rawurl)
- }
- default:
- if client.GetHttpProxy() != "" {
- proxy, err = url.Parse(client.httpProxy)
- } else if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
- proxy, err = url.Parse(rawurl)
- } else if rawurl := os.Getenv("http_proxy"); rawurl != "" {
- proxy, err = url.Parse(rawurl)
- }
- }
- return
- }
-
- func (client *Client) getNoProxy(scheme string) []string {
- var urls []string
- if client.GetNoProxy() != "" {
- urls = strings.Split(client.noProxy, ",")
- } else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
- urls = strings.Split(rawurl, ",")
- } else if rawurl := os.Getenv("no_proxy"); rawurl != "" {
- urls = strings.Split(rawurl, ",")
- }
- return urls
- }
-
- func hookDo(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
- return fn
- }
|