ghttp_client_config.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package ghttp
  7. import (
  8. "context"
  9. "crypto/tls"
  10. "github.com/gogf/gf/text/gstr"
  11. "golang.org/x/net/proxy"
  12. "net"
  13. "net/http"
  14. "net/url"
  15. "strings"
  16. "time"
  17. "github.com/gogf/gf/text/gregex"
  18. )
  19. // Client is the HTTP client for HTTP request management.
  20. type Client struct {
  21. http.Client // Underlying HTTP Client.
  22. ctx context.Context // Context for each request.
  23. parent *Client // Parent http client, this is used for chaining operations.
  24. header map[string]string // Custom header map.
  25. cookies map[string]string // Custom cookie map.
  26. prefix string // Prefix for request.
  27. authUser string // HTTP basic authentication: user.
  28. authPass string // HTTP basic authentication: pass.
  29. browserMode bool // Whether auto saving and sending cookie content.
  30. retryCount int // Retry count when request fails.
  31. retryInterval time.Duration // Retry interval when request fails.
  32. }
  33. // NewClient creates and returns a new HTTP client object.
  34. func NewClient() *Client {
  35. return &Client{
  36. Client: http.Client{
  37. Transport: &http.Transport{
  38. // No validation for https certification of the server in default.
  39. TLSClientConfig: &tls.Config{
  40. InsecureSkipVerify: true,
  41. },
  42. DisableKeepAlives: true,
  43. },
  44. },
  45. header: make(map[string]string),
  46. cookies: make(map[string]string),
  47. }
  48. }
  49. // Clone clones current client and returns a new one.
  50. func (c *Client) Clone() *Client {
  51. newClient := NewClient()
  52. *newClient = *c
  53. newClient.header = make(map[string]string)
  54. newClient.cookies = make(map[string]string)
  55. for k, v := range c.header {
  56. newClient.header[k] = v
  57. }
  58. for k, v := range c.cookies {
  59. newClient.cookies[k] = v
  60. }
  61. return newClient
  62. }
  63. // SetBrowserMode enables browser mode of the client.
  64. // When browser mode is enabled, it automatically saves and sends cookie content
  65. // from and to server.
  66. func (c *Client) SetBrowserMode(enabled bool) *Client {
  67. c.browserMode = enabled
  68. return c
  69. }
  70. // SetHeader sets a custom HTTP header pair for the client.
  71. func (c *Client) SetHeader(key, value string) *Client {
  72. c.header[key] = value
  73. return c
  74. }
  75. // SetHeaderMap sets custom HTTP headers with map.
  76. func (c *Client) SetHeaderMap(m map[string]string) *Client {
  77. for k, v := range m {
  78. c.header[k] = v
  79. }
  80. return c
  81. }
  82. // SetContentType sets HTTP content type for the client.
  83. func (c *Client) SetContentType(contentType string) *Client {
  84. c.header["Content-Type"] = contentType
  85. return c
  86. }
  87. // SetHeaderRaw sets custom HTTP header using raw string.
  88. func (c *Client) SetHeaderRaw(headers string) *Client {
  89. for _, line := range gstr.SplitAndTrim(headers, "\n") {
  90. array, _ := gregex.MatchString(`^([\w\-]+):\s*(.+)`, line)
  91. if len(array) >= 3 {
  92. c.header[array[1]] = array[2]
  93. }
  94. }
  95. return c
  96. }
  97. // SetCookie sets a cookie pair for the client.
  98. func (c *Client) SetCookie(key, value string) *Client {
  99. c.cookies[key] = value
  100. return c
  101. }
  102. // SetCookieMap sets cookie items with map.
  103. func (c *Client) SetCookieMap(m map[string]string) *Client {
  104. for k, v := range m {
  105. c.cookies[k] = v
  106. }
  107. return c
  108. }
  109. // SetPrefix sets the request server URL prefix.
  110. func (c *Client) SetPrefix(prefix string) *Client {
  111. c.prefix = prefix
  112. return c
  113. }
  114. // SetTimeOut sets the request timeout for the client.
  115. func (c *Client) SetTimeout(t time.Duration) *Client {
  116. c.Client.Timeout = t
  117. return c
  118. }
  119. // SetBasicAuth sets HTTP basic authentication information for the client.
  120. func (c *Client) SetBasicAuth(user, pass string) *Client {
  121. c.authUser = user
  122. c.authPass = pass
  123. return c
  124. }
  125. // SetCtx sets context for each request of this client.
  126. func (c *Client) SetCtx(ctx context.Context) *Client {
  127. c.ctx = ctx
  128. return c
  129. }
  130. // SetRetry sets retry count and interval.
  131. func (c *Client) SetRetry(retryCount int, retryInterval time.Duration) *Client {
  132. c.retryCount = retryCount
  133. c.retryInterval = retryInterval
  134. return c
  135. }
  136. // SetRedirectLimit limit the number of jumps
  137. func (c *Client) SetRedirectLimit(redirectLimit int) *Client {
  138. c.CheckRedirect = func(req *http.Request, via []*http.Request) error {
  139. if len(via) >= redirectLimit {
  140. return http.ErrUseLastResponse
  141. }
  142. return nil
  143. }
  144. return c
  145. }
  146. // SetProxy set proxy for the client.
  147. // This func will do nothing when the parameter `proxyURL` is empty or in wrong pattern.
  148. // The correct pattern is like `http://USER:PASSWORD@IP:PORT` or `socks5://USER:PASSWORD@IP:PORT`.
  149. // Only `http` and `socks5` proxies are supported currently.
  150. func (c *Client) SetProxy(proxyURL string) {
  151. if strings.TrimSpace(proxyURL) == "" {
  152. return
  153. }
  154. _proxy, err := url.Parse(proxyURL)
  155. if err != nil {
  156. return
  157. }
  158. if _proxy.Scheme == "http" {
  159. if _, ok := c.Transport.(*http.Transport); ok {
  160. c.Transport.(*http.Transport).Proxy = http.ProxyURL(_proxy)
  161. }
  162. } else {
  163. var auth = &proxy.Auth{}
  164. user := _proxy.User.Username()
  165. if user != "" {
  166. auth.User = user
  167. password, hasPassword := _proxy.User.Password()
  168. if hasPassword && password != "" {
  169. auth.Password = password
  170. }
  171. } else {
  172. auth = nil
  173. }
  174. // refer to the source code, error is always nil
  175. dialer, err := proxy.SOCKS5(
  176. "tcp",
  177. _proxy.Host,
  178. auth,
  179. &net.Dialer{
  180. Timeout: c.Client.Timeout,
  181. KeepAlive: c.Client.Timeout,
  182. },
  183. )
  184. if err != nil {
  185. return
  186. }
  187. if _, ok := c.Transport.(*http.Transport); ok {
  188. c.Transport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (conn net.Conn, e error) {
  189. return dialer.Dial(network, addr)
  190. }
  191. }
  192. //c.SetTimeout(10*time.Second)
  193. }
  194. }