暫無描述
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.

http_factory.go 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. package factory
  2. import (
  3. "encoding/base64"
  4. "fmt"
  5. "net/http"
  6. "sync"
  7. "time"
  8. "git.x2erp.com/qdy/go-base/config"
  9. "github.com/go-resty/resty/v2"
  10. )
  11. // HTTPClient 简化的HTTP客户端
  12. type HTTPClient struct {
  13. client *resty.Client
  14. }
  15. // HTTPFactory HTTP客户端工厂
  16. type HTTPFactory struct {
  17. config config.IConfig
  18. client *resty.Client
  19. }
  20. var (
  21. httpFactoryInstance *HTTPFactory
  22. httpFactoryOnce sync.Once
  23. httpFactoryInitErr error
  24. )
  25. // GetHTTPFactory 获取HTTP工厂单例实例
  26. func GetHTTPFactory() (*HTTPFactory, error) {
  27. httpFactoryOnce.Do(func() {
  28. cfg := config.GetConfig()
  29. if err := config.GetInitError(); err != nil {
  30. httpFactoryInitErr = fmt.Errorf("failed to load config: %v", err)
  31. return
  32. }
  33. httpConfig := cfg.GetHTTP()
  34. // 创建共享的resty客户端(线程安全)
  35. client := resty.New()
  36. client.SetTimeout(time.Duration(httpConfig.Timeout) * time.Second)
  37. client.SetTransport(&http.Transport{
  38. MaxIdleConns: httpConfig.MaxIdleConns,
  39. MaxIdleConnsPerHost: httpConfig.MaxIdleConnsPerHost,
  40. IdleConnTimeout: time.Duration(httpConfig.IdleConnTimeout) * time.Second,
  41. MaxConnsPerHost: httpConfig.MaxConnsPerHost,
  42. DisableCompression: httpConfig.DisableCompression,
  43. DisableKeepAlives: httpConfig.DisableKeepAlives,
  44. })
  45. // 设置默认headers
  46. client.SetHeaders(map[string]string{
  47. "Content-Type": "application/json",
  48. "Accept": "application/json",
  49. })
  50. httpFactoryInstance = &HTTPFactory{
  51. config: cfg,
  52. client: client,
  53. }
  54. })
  55. return httpFactoryInstance, httpFactoryInitErr
  56. }
  57. // CreateClient 创建HTTP客户端包装器(共享底层resty.Client)
  58. func (f *HTTPFactory) CreateClient() *HTTPClient {
  59. return &HTTPClient{
  60. client: f.client, // 共享同一个线程安全的客户端
  61. }
  62. }
  63. // CreateClient 全局便捷函数:创建HTTP客户端
  64. func CreateClient() (*HTTPClient, error) {
  65. factory, err := GetHTTPFactory()
  66. if err != nil {
  67. return nil, err
  68. }
  69. return factory.CreateClient(), nil
  70. }
  71. // GetInitError 获取初始化错误(如果有)
  72. func GetInitError() error {
  73. return httpFactoryInitErr
  74. }
  75. // ==================== HTTPClient 方法 ====================
  76. // SetAuthToken 设置认证token(请求级别)
  77. func (c *HTTPClient) SetAuthToken(token string) *HTTPClient {
  78. // 注意:这里设置的是客户端级别的token,会影响所有使用该客户端的请求
  79. // 对于多用户场景,应该在请求级别设置
  80. c.client.SetAuthToken(token)
  81. return c
  82. }
  83. // SetBearerToken 设置Bearer Token认证头(请求级别)
  84. func (c *HTTPClient) SetBearerToken(token string) *HTTPClient {
  85. if token != "" {
  86. c.client.SetHeader("Authorization", "Bearer "+token)
  87. } else {
  88. c.client.Header.Del("Authorization")
  89. }
  90. return c
  91. }
  92. // SetBasicAuth 设置Basic认证头(请求级别)
  93. func (c *HTTPClient) SetBasicAuth(username, password string) *HTTPClient {
  94. if username != "" && password != "" {
  95. auth := username + ":" + password
  96. token := base64.StdEncoding.EncodeToString([]byte(auth))
  97. c.client.SetHeader("Authorization", "Basic "+token)
  98. } else {
  99. c.client.Header.Del("Authorization")
  100. }
  101. return c
  102. }
  103. // SetJSONContentType 设置Content-Type为application/json
  104. func (c *HTTPClient) SetJSONContentType() *HTTPClient {
  105. c.client.SetHeader("Content-Type", "application/json")
  106. return c
  107. }
  108. // SetHeader 设置请求头
  109. func (c *HTTPClient) SetHeader(key, value string) *HTTPClient {
  110. c.client.SetHeader(key, value)
  111. return c
  112. }
  113. // SetHeaders 批量设置请求头
  114. func (c *HTTPClient) SetHeaders(headers map[string]string) *HTTPClient {
  115. c.client.SetHeaders(headers)
  116. return c
  117. }
  118. // SetAuthHeaders 设置认证相关的headers
  119. func (c *HTTPClient) SetAuthHeaders(token string) *HTTPClient {
  120. return c.SetJSONContentType().SetBearerToken(token)
  121. }
  122. // SetBasicAuthHeaders 设置Basic认证相关的headers
  123. func (c *HTTPClient) SetBasicAuthHeaders(username, password string) *HTTPClient {
  124. return c.SetJSONContentType().SetBasicAuth(username, password)
  125. }
  126. // Post 发送POST请求(在请求级别设置认证信息,避免多用户相互影响)
  127. func (c *HTTPClient) Post(url string, data interface{}) (*resty.Response, error) {
  128. return c.client.R().SetBody(data).Post(url)
  129. }
  130. // PostWithResult 发送POST请求并解析结果
  131. func (c *HTTPClient) PostWithResult(url string, data interface{}, result interface{}) (*resty.Response, error) {
  132. return c.client.R().SetBody(data).SetResult(result).Post(url)
  133. }
  134. // PostWithAuth 发送带Bearer Token的POST请求(推荐用于多用户场景)
  135. func (c *HTTPClient) PostWithAuth(url string, data interface{}, token string, result interface{}) (*resty.Response, error) {
  136. req := c.client.R().SetBody(data)
  137. if token != "" {
  138. req.SetHeader("Authorization", "Bearer "+token)
  139. }
  140. if result != nil {
  141. req.SetResult(result)
  142. }
  143. return req.Post(url)
  144. }
  145. // Get 发送GET请求
  146. func (c *HTTPClient) Get(url string) (*resty.Response, error) {
  147. return c.client.R().Get(url)
  148. }
  149. // GetWithResult 发送GET请求并解析结果
  150. func (c *HTTPClient) GetWithResult(url string, result interface{}) (*resty.Response, error) {
  151. return c.client.R().SetResult(result).Get(url)
  152. }
  153. // GetWithAuth 发送带Bearer Token的GET请求(推荐用于多用户场景)
  154. func (c *HTTPClient) GetWithAuth(url string, token string, result interface{}) (*resty.Response, error) {
  155. req := c.client.R()
  156. if token != "" {
  157. req.SetHeader("Authorization", "Bearer "+token)
  158. }
  159. if result != nil {
  160. req.SetResult(result)
  161. }
  162. return req.Get(url)
  163. }
  164. // Put 发送PUT请求
  165. func (c *HTTPClient) Put(url string, data interface{}) (*resty.Response, error) {
  166. return c.client.R().SetBody(data).Put(url)
  167. }
  168. // PutWithResult 发送PUT请求并解析结果
  169. func (c *HTTPClient) PutWithResult(url string, data interface{}, result interface{}) (*resty.Response, error) {
  170. return c.client.R().SetBody(data).SetResult(result).Put(url)
  171. }
  172. // Delete 发送DELETE请求
  173. func (c *HTTPClient) Delete(url string) (*resty.Response, error) {
  174. return c.client.R().Delete(url)
  175. }
  176. // DeleteWithResult 发送DELETE请求并解析结果
  177. func (c *HTTPClient) DeleteWithResult(url string, result interface{}) (*resty.Response, error) {
  178. return c.client.R().SetResult(result).Delete(url)
  179. }
  180. // ==================== 便捷函数(修正版) ====================
  181. // PostJSON 便捷函数:直接发送POST请求
  182. func PostJSON(url string, data interface{}, result interface{}) (*resty.Response, error) {
  183. client, err := CreateClient()
  184. if err != nil {
  185. return nil, err
  186. }
  187. if result != nil {
  188. return client.PostWithResult(url, data, result)
  189. }
  190. return client.Post(url, data)
  191. }
  192. // PostJSONWithBearerToken 便捷函数:使用Bearer Token发送POST请求
  193. func PostJSONWithBearerToken(token, url string, data interface{}, result interface{}) (*resty.Response, error) {
  194. client, err := CreateClient()
  195. if err != nil {
  196. return nil, err
  197. }
  198. return client.PostWithAuth(url, data, token, result)
  199. }
  200. // PostJSONWithBasicAuth 便捷函数:使用Basic认证发送POST请求
  201. func PostJSONWithBasicAuth(username, password, url string, data interface{}, result interface{}) (*resty.Response, error) {
  202. client, err := CreateClient()
  203. if err != nil {
  204. return nil, err
  205. }
  206. // 为这个特定请求设置Basic Auth
  207. req := client.client.R().SetBody(data)
  208. if username != "" && password != "" {
  209. auth := username + ":" + password
  210. token := base64.StdEncoding.EncodeToString([]byte(auth))
  211. req.SetHeader("Authorization", "Basic "+token)
  212. }
  213. if result != nil {
  214. req.SetResult(result)
  215. }
  216. return req.Post(url)
  217. }
  218. // GetJSON 便捷函数:直接发送GET请求
  219. func GetJSON(url string, result interface{}) (*resty.Response, error) {
  220. client, err := CreateClient()
  221. if err != nil {
  222. return nil, err
  223. }
  224. if result != nil {
  225. return client.GetWithResult(url, result)
  226. }
  227. return client.Get(url)
  228. }
  229. // GetJSONWithBearerToken 便捷函数:使用Bearer Token发送GET请求
  230. func GetJSONWithBearerToken(token, url string, result interface{}) (*resty.Response, error) {
  231. client, err := CreateClient()
  232. if err != nil {
  233. return nil, err
  234. }
  235. return client.GetWithAuth(url, token, result)
  236. }
  237. // GetJSONWithBasicAuth 便捷函数:使用Basic认证发送GET请求
  238. func GetJSONWithBasicAuth(username, password, url string, result interface{}) (*resty.Response, error) {
  239. client, err := CreateClient()
  240. if err != nil {
  241. return nil, err
  242. }
  243. // 为这个特定请求设置Basic Auth
  244. req := client.client.R()
  245. if username != "" && password != "" {
  246. auth := username + ":" + password
  247. token := base64.StdEncoding.EncodeToString([]byte(auth))
  248. req.SetHeader("Authorization", "Basic "+token)
  249. }
  250. if result != nil {
  251. req.SetResult(result)
  252. }
  253. return req.Get(url)
  254. }