You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
8.1 KiB

  1. package sdk
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "fmt"
  6. "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth"
  7. "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/credentials"
  8. "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
  9. "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses"
  10. "net"
  11. "net/http"
  12. "net/url"
  13. "os"
  14. "regexp"
  15. "runtime"
  16. "strings"
  17. "time"
  18. )
  19. var Version = "0.0.1"
  20. var defaultConnectTimeout = 5 * time.Second
  21. var defaultReadTimeout = 10 * time.Second
  22. var DefaultUserAgent = fmt.Sprintf("GaoreGoSdk (%s;%s) Golang/%s Core/%s", runtime.GOOS, runtime.GOARCH, strings.Trim(runtime.Version(), "go"), Version)
  23. type Client struct {
  24. Host string
  25. httpClient *http.Client
  26. isInsecure bool
  27. signer auth.Signer
  28. readTimeout time.Duration
  29. connectTimeout time.Duration
  30. config *Config
  31. httpProxy string
  32. httpsProxy string
  33. noProxy string
  34. }
  35. func (client *Client) GetNoProxy() string {
  36. return client.noProxy
  37. }
  38. func (client *Client) SetNoProxy(noProxy string) {
  39. client.noProxy = noProxy
  40. }
  41. func (client *Client) GetHttpsProxy() string {
  42. return client.httpsProxy
  43. }
  44. func (client *Client) SetHttpsProxy(httpsProxy string) {
  45. client.httpsProxy = httpsProxy
  46. }
  47. func (client *Client) SetHttpProxy(httpProxy string) {
  48. client.httpProxy = httpProxy
  49. }
  50. func (client *Client) GetHttpProxy() string {
  51. return client.httpProxy
  52. }
  53. func (client *Client) GetHTTPSInsecure() bool {
  54. return client.isInsecure
  55. }
  56. func (client *Client) InitClientConfig() (config *Config) {
  57. if client.config != nil {
  58. return client.config
  59. } else {
  60. return NewConfig()
  61. }
  62. }
  63. func (client *Client) InitWithAccessKey(accessKeyId, accessKeySecret, source string) (err error) {
  64. config := client.InitWithConfig()
  65. credential := &credentials.BaseCredential{
  66. AccessKeyId: accessKeyId,
  67. AccessKeySecret: accessKeySecret,
  68. }
  69. return client.InitWithOptions("", config, credential)
  70. }
  71. func (client *Client) InitWithOptions(host string, config *Config, credential auth.Credential) (err error) {
  72. client.httpClient = &http.Client{}
  73. if config.Transport != nil {
  74. client.httpClient.Transport = config.Transport
  75. } else if config.HttpTransport != nil {
  76. client.httpClient.Transport = config.HttpTransport
  77. }
  78. if config.Timeout > 0 {
  79. client.httpClient.Timeout = config.Timeout
  80. }
  81. client.signer, err = auth.NewSignerWithCredential(credential, client.ProcessCommonRequestWithSigner)
  82. return nil
  83. }
  84. func (client *Client) InitWithConfig() (config *Config) {
  85. if client.config != nil {
  86. return client.config
  87. } else {
  88. return NewConfig()
  89. }
  90. }
  91. func (client *Client) ProcessCommonRequestWithSigner(request *requests.CommonRequest, signerInterface interface{}) (response *responses.CommonResponse, err error) {
  92. if signer, isSigner := signerInterface.(auth.Signer); isSigner {
  93. response = responses.NewCommonResponse()
  94. err = client.DoActionWithSigner(request, response, signer)
  95. return
  96. }
  97. panic("should not be here")
  98. }
  99. func Timeout(connectTimeout time.Duration) func(ctx context.Context, net, addr string) (c net.Conn, err error) {
  100. return func(ctx context.Context, network, address string) (c net.Conn, err error) {
  101. return (&net.Dialer{
  102. Timeout: connectTimeout,
  103. DualStack: true,
  104. }).DialContext(ctx, network, address)
  105. }
  106. }
  107. func (client *Client) setTimeOut(request requests.AcsRequest) {
  108. readTimeout, connectTimeout := client.getTimeOut(request)
  109. client.httpClient.Timeout = readTimeout
  110. if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil {
  111. trans.DialContext = Timeout(connectTimeout)
  112. client.httpClient.Transport = trans
  113. } else if client.httpClient.Transport == nil {
  114. client.httpClient.Transport = &http.Transport{
  115. DialContext: Timeout(connectTimeout),
  116. }
  117. }
  118. }
  119. func (client *Client) getTimeOut(request requests.AcsRequest) (time.Duration, time.Duration) {
  120. readTimeOut := defaultReadTimeout
  121. connectTimeOut := defaultConnectTimeout
  122. reqReadTimeout := request.GetReadTimeout()
  123. reqConnectTimeout := request.GetConnectTimeout()
  124. if reqReadTimeout != 0*time.Millisecond {
  125. readTimeOut = reqReadTimeout
  126. } else if client.readTimeout != 0*time.Microsecond {
  127. readTimeOut = client.readTimeout
  128. } else if client.httpClient.Timeout != 0 {
  129. readTimeOut = client.httpClient.Timeout
  130. }
  131. if reqConnectTimeout != 0*time.Microsecond {
  132. connectTimeOut = reqConnectTimeout
  133. } else if client.connectTimeout != 0*time.Millisecond {
  134. connectTimeOut = client.connectTimeout
  135. }
  136. return readTimeOut, connectTimeOut
  137. }
  138. func (client *Client) getHTTPSInsecure(request requests.AcsRequest) (insecure bool) {
  139. if request.GetHTTPSInsecure() != nil {
  140. insecure = *request.GetHTTPSInsecure()
  141. } else {
  142. insecure = client.GetHTTPSInsecure()
  143. }
  144. return
  145. }
  146. func (client *Client) DoAction(request requests.AcsRequest, response responses.AcsResponse) (err error) {
  147. return client.DoActionWithSigner(request, response, nil)
  148. }
  149. func (client *Client) DoActionWithSigner(request requests.AcsRequest, response responses.AcsResponse, signer auth.Signer) (err error) {
  150. httpRequest, err := client.buildRequestWithSigner(request, signer)
  151. if err != nil {
  152. return err
  153. }
  154. client.setTimeOut(request)
  155. proxy, err := client.getHttpProxy(httpRequest.URL.Scheme)
  156. if err != nil {
  157. return err
  158. }
  159. noProxy := client.getNoProxy(httpRequest.URL.Scheme)
  160. var flag bool
  161. for _, value := range noProxy {
  162. if strings.HasPrefix(value, "*") {
  163. value = fmt.Sprint(".%s", value)
  164. }
  165. noProxyReg, err := regexp.Compile(value)
  166. if err != nil {
  167. return err
  168. }
  169. if noProxyReg.MatchString(httpRequest.Host) {
  170. flag = true
  171. break
  172. }
  173. }
  174. if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil {
  175. if trans.TLSClientConfig != nil {
  176. trans.TLSClientConfig.InsecureSkipVerify = client.getHTTPSInsecure(request)
  177. } else {
  178. trans.TLSClientConfig = &tls.Config{
  179. InsecureSkipVerify: client.getHTTPSInsecure(request),
  180. }
  181. }
  182. if proxy != nil && !flag {
  183. trans.Proxy = http.ProxyURL(proxy)
  184. }
  185. client.httpClient.Transport = trans
  186. }
  187. var httpResponse *http.Response
  188. httpResponse, err = hookDo(client.httpClient.Do)(httpRequest)
  189. if err == nil {
  190. for key, val := range httpResponse.Header {
  191. fmt.Println(key, val)
  192. }
  193. }
  194. return
  195. }
  196. func (client *Client) buildRequestWithSigner(request requests.AcsRequest, signer auth.Signer) (httpRequest *http.Request, err error) {
  197. // init param
  198. request.SetDomain("")
  199. if request.GetScheme() == "" {
  200. request.SetScheme(client.config.Scheme)
  201. }
  202. err = requests.InitParam(request)
  203. if err != nil {
  204. return
  205. }
  206. // build request
  207. err = auth.Sign(request, signer)
  208. if err != nil {
  209. return
  210. }
  211. requestMethod := request.GetMethod()
  212. requestUrl := request.BuildUrl()
  213. body := request.GetBodyReader()
  214. httpRequest, err = http.NewRequest(requestMethod, requestUrl, body)
  215. if err != nil {
  216. return
  217. }
  218. for key, val := range request.GetHeaders() {
  219. httpRequest.Header[key] = []string{val}
  220. }
  221. if host, isContainsHost := request.GetHeaders()["host"]; isContainsHost {
  222. httpRequest.Host = host
  223. }
  224. userAgent := DefaultUserAgent
  225. httpRequest.Header.Set("User-Agent", userAgent)
  226. return
  227. }
  228. func (client *Client) getHttpProxy(scheme string) (proxy *url.URL, err error) {
  229. switch scheme {
  230. case "https":
  231. if client.GetHttpsProxy() != "" {
  232. proxy, err = url.Parse(client.httpsProxy)
  233. } else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
  234. proxy, err = url.Parse(rawurl)
  235. } else if rawurl := os.Getenv("https_proxy"); rawurl != "" {
  236. proxy, err = url.Parse(rawurl)
  237. }
  238. default:
  239. if client.GetHttpProxy() != "" {
  240. proxy, err = url.Parse(client.httpProxy)
  241. } else if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
  242. proxy, err = url.Parse(rawurl)
  243. } else if rawurl := os.Getenv("http_proxy"); rawurl != "" {
  244. proxy, err = url.Parse(rawurl)
  245. }
  246. }
  247. return
  248. }
  249. func (client *Client) getNoProxy(scheme string) []string {
  250. var urls []string
  251. if client.GetNoProxy() != "" {
  252. urls = strings.Split(client.noProxy, ",")
  253. } else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
  254. urls = strings.Split(rawurl, ",")
  255. } else if rawurl := os.Getenv("no_proxy"); rawurl != "" {
  256. urls = strings.Split(rawurl, ",")
  257. }
  258. return urls
  259. }
  260. func hookDo(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
  261. return fn
  262. }