Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

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