gclient.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright GoFrame Author(https://goframe.org). 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 gclient provides convenient http client functionalities.
  7. package gclient
  8. import (
  9. "crypto/rand"
  10. "crypto/tls"
  11. "fmt"
  12. "net/http"
  13. "os"
  14. "time"
  15. "github.com/gogf/gf/v2"
  16. "github.com/gogf/gf/v2/errors/gerror"
  17. "github.com/gogf/gf/v2/net/gsel"
  18. "github.com/gogf/gf/v2/os/gfile"
  19. )
  20. // Client is the HTTP client for HTTP request management.
  21. type Client struct {
  22. http.Client // Underlying HTTP Client.
  23. header map[string]string // Custom header map.
  24. cookies map[string]string // Custom cookie map.
  25. prefix string // Prefix for request.
  26. authUser string // HTTP basic authentication: user.
  27. authPass string // HTTP basic authentication: pass.
  28. retryCount int // Retry count when request fails.
  29. retryInterval time.Duration // Retry interval when request fails.
  30. middlewareHandler []HandlerFunc // Interceptor handlers
  31. selectorBuilder gsel.Builder // Builder for request balance.
  32. }
  33. const (
  34. httpProtocolName = `http`
  35. httpParamFileHolder = `@file:`
  36. httpRegexParamJson = `^[\w\[\]]+=.+`
  37. httpRegexHeaderRaw = `^([\w\-]+):\s*(.+)`
  38. httpHeaderHost = `Host`
  39. httpHeaderCookie = `Cookie`
  40. httpHeaderUserAgent = `User-Agent`
  41. httpHeaderContentType = `Content-Type`
  42. httpHeaderContentTypeJson = `application/json`
  43. httpHeaderContentTypeXml = `application/xml`
  44. httpHeaderContentTypeForm = `application/x-www-form-urlencoded`
  45. )
  46. var (
  47. hostname, _ = os.Hostname()
  48. defaultClientAgent = fmt.Sprintf(`GClient %s at %s`, gf.VERSION, hostname)
  49. )
  50. // New creates and returns a new HTTP client object.
  51. func New() *Client {
  52. c := &Client{
  53. Client: http.Client{
  54. Transport: &http.Transport{
  55. // No validation for https certification of the server in default.
  56. TLSClientConfig: &tls.Config{
  57. InsecureSkipVerify: true,
  58. },
  59. DisableKeepAlives: true,
  60. },
  61. },
  62. header: make(map[string]string),
  63. cookies: make(map[string]string),
  64. }
  65. c.header[httpHeaderUserAgent] = defaultClientAgent
  66. // It enables OpenTelemetry for client in default.
  67. c.Use(internalMiddlewareTracing, internalMiddlewareDiscovery)
  68. return c
  69. }
  70. // Clone deeply clones current client and returns a new one.
  71. func (c *Client) Clone() *Client {
  72. newClient := New()
  73. *newClient = *c
  74. if len(c.header) > 0 {
  75. newClient.header = make(map[string]string)
  76. for k, v := range c.header {
  77. newClient.header[k] = v
  78. }
  79. }
  80. if len(c.cookies) > 0 {
  81. newClient.cookies = make(map[string]string)
  82. for k, v := range c.cookies {
  83. newClient.cookies[k] = v
  84. }
  85. }
  86. return newClient
  87. }
  88. // LoadKeyCrt creates and returns a TLS configuration object with given certificate and key files.
  89. func LoadKeyCrt(crtFile, keyFile string) (*tls.Config, error) {
  90. crtPath, err := gfile.Search(crtFile)
  91. if err != nil {
  92. return nil, err
  93. }
  94. keyPath, err := gfile.Search(keyFile)
  95. if err != nil {
  96. return nil, err
  97. }
  98. crt, err := tls.LoadX509KeyPair(crtPath, keyPath)
  99. if err != nil {
  100. err = gerror.Wrapf(err, `tls.LoadX509KeyPair failed for certFile "%s", keyFile "%s"`, crtPath, keyPath)
  101. return nil, err
  102. }
  103. tlsConfig := &tls.Config{}
  104. tlsConfig.Certificates = []tls.Certificate{crt}
  105. tlsConfig.Time = time.Now
  106. tlsConfig.Rand = rand.Reader
  107. return tlsConfig, nil
  108. }