설명 없음
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.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. package http
  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. // GetUnderlyingClient 获取底层resty客户端(用于特殊场景)
  64. func (f *HTTPFactory) GetUnderlyingClient() *resty.Client {
  65. if f == nil {
  66. return nil
  67. }
  68. return f.client
  69. }
  70. // CreateClient 全局便捷函数:创建HTTP客户端
  71. func CreateClient() (*HTTPClient, error) {
  72. factory, err := GetHTTPFactory()
  73. if err != nil {
  74. return nil, err
  75. }
  76. return factory.CreateClient(), nil
  77. }
  78. // GetInitError 获取初始化错误(如果有)
  79. func GetInitError() error {
  80. return httpFactoryInitErr
  81. }
  82. // ==================== HTTPClient 方法 ====================
  83. // SetAuthToken 设置认证token(请求级别)
  84. func (c *HTTPClient) SetAuthToken(token string) *HTTPClient {
  85. // 注意:这里设置的是客户端级别的token,会影响所有使用该客户端的请求
  86. // 对于多用户场景,应该在请求级别设置
  87. c.client.SetAuthToken(token)
  88. return c
  89. }
  90. // SetBearerToken 设置Bearer Token认证头(请求级别)
  91. func (c *HTTPClient) SetBearerToken(token string) *HTTPClient {
  92. if token != "" {
  93. c.client.SetHeader("Authorization", "Bearer "+token)
  94. } else {
  95. c.client.Header.Del("Authorization")
  96. }
  97. return c
  98. }
  99. // SetBasicAuth 设置Basic认证头(请求级别)
  100. func (c *HTTPClient) SetBasicAuth(username, password string) *HTTPClient {
  101. if username != "" && password != "" {
  102. auth := username + ":" + password
  103. token := base64.StdEncoding.EncodeToString([]byte(auth))
  104. c.client.SetHeader("Authorization", "Basic "+token)
  105. } else {
  106. c.client.Header.Del("Authorization")
  107. }
  108. return c
  109. }
  110. // SetJSONContentType 设置Content-Type为application/json
  111. func (c *HTTPClient) SetJSONContentType() *HTTPClient {
  112. c.client.SetHeader("Content-Type", "application/json")
  113. return c
  114. }
  115. // SetHeader 设置请求头
  116. func (c *HTTPClient) SetHeader(key, value string) *HTTPClient {
  117. c.client.SetHeader(key, value)
  118. return c
  119. }
  120. // SetHeaders 批量设置请求头
  121. func (c *HTTPClient) SetHeaders(headers map[string]string) *HTTPClient {
  122. c.client.SetHeaders(headers)
  123. return c
  124. }
  125. // SetAuthHeaders 设置认证相关的headers
  126. func (c *HTTPClient) SetAuthHeaders(token string) *HTTPClient {
  127. return c.SetJSONContentType().SetBearerToken(token)
  128. }
  129. // SetBasicAuthHeaders 设置Basic认证相关的headers
  130. func (c *HTTPClient) SetBasicAuthHeaders(username, password string) *HTTPClient {
  131. return c.SetJSONContentType().SetBasicAuth(username, password)
  132. }
  133. // Post 发送POST请求(在请求级别设置认证信息,避免多用户相互影响)
  134. func (c *HTTPClient) Post(url string, data interface{}) (*resty.Response, error) {
  135. return c.client.R().SetBody(data).Post(url)
  136. }
  137. // PostWithResult 发送POST请求并解析结果
  138. func (c *HTTPClient) PostWithResult(url string, data interface{}, result interface{}) (*resty.Response, error) {
  139. return c.client.R().SetBody(data).SetResult(result).Post(url)
  140. }
  141. // PostWithAuth 发送带Bearer Token的POST请求(推荐用于多用户场景)
  142. func (c *HTTPClient) PostWithAuth(url string, data interface{}, token string, result interface{}) (*resty.Response, error) {
  143. req := c.client.R().SetBody(data)
  144. if token != "" {
  145. req.SetHeader("Authorization", "Bearer "+token)
  146. }
  147. if result != nil {
  148. req.SetResult(result)
  149. }
  150. return req.Post(url)
  151. }
  152. // Get 发送GET请求
  153. func (c *HTTPClient) Get(url string) (*resty.Response, error) {
  154. return c.client.R().Get(url)
  155. }
  156. // GetWithResult 发送GET请求并解析结果
  157. func (c *HTTPClient) GetWithResult(url string, result interface{}) (*resty.Response, error) {
  158. return c.client.R().SetResult(result).Get(url)
  159. }
  160. // GetWithAuth 发送带Bearer Token的GET请求(推荐用于多用户场景)
  161. func (c *HTTPClient) GetWithAuth(url string, token string, result interface{}) (*resty.Response, error) {
  162. req := c.client.R()
  163. if token != "" {
  164. req.SetHeader("Authorization", "Bearer "+token)
  165. }
  166. if result != nil {
  167. req.SetResult(result)
  168. }
  169. return req.Get(url)
  170. }
  171. // Put 发送PUT请求
  172. func (c *HTTPClient) Put(url string, data interface{}) (*resty.Response, error) {
  173. return c.client.R().SetBody(data).Put(url)
  174. }
  175. // PutWithResult 发送PUT请求并解析结果
  176. func (c *HTTPClient) PutWithResult(url string, data interface{}, result interface{}) (*resty.Response, error) {
  177. return c.client.R().SetBody(data).SetResult(result).Put(url)
  178. }
  179. // Delete 发送DELETE请求
  180. func (c *HTTPClient) Delete(url string) (*resty.Response, error) {
  181. return c.client.R().Delete(url)
  182. }
  183. // DeleteWithResult 发送DELETE请求并解析结果
  184. func (c *HTTPClient) DeleteWithResult(url string, result interface{}) (*resty.Response, error) {
  185. return c.client.R().SetResult(result).Delete(url)
  186. }
  187. // ==================== 便捷函数(修正版) ====================
  188. // PostJSON 便捷函数:直接发送POST请求
  189. func PostJSON(url string, data interface{}, result interface{}) (*resty.Response, error) {
  190. client, err := CreateClient()
  191. if err != nil {
  192. return nil, err
  193. }
  194. if result != nil {
  195. return client.PostWithResult(url, data, result)
  196. }
  197. return client.Post(url, data)
  198. }
  199. // PostJSONWithBearerToken 便捷函数:使用Bearer Token发送POST请求
  200. func PostJSONWithBearerToken(token, url string, data interface{}, result interface{}) (*resty.Response, error) {
  201. client, err := CreateClient()
  202. if err != nil {
  203. return nil, err
  204. }
  205. return client.PostWithAuth(url, data, token, result)
  206. }
  207. // PostJSONWithBasicAuth 便捷函数:使用Basic认证发送POST请求
  208. func PostJSONWithBasicAuth(username, password, url string, data interface{}, result interface{}) (*resty.Response, error) {
  209. client, err := CreateClient()
  210. if err != nil {
  211. return nil, err
  212. }
  213. // 为这个特定请求设置Basic Auth
  214. req := client.client.R().SetBody(data)
  215. if username != "" && password != "" {
  216. auth := username + ":" + password
  217. token := base64.StdEncoding.EncodeToString([]byte(auth))
  218. req.SetHeader("Authorization", "Basic "+token)
  219. }
  220. if result != nil {
  221. req.SetResult(result)
  222. }
  223. return req.Post(url)
  224. }
  225. // GetJSON 便捷函数:直接发送GET请求
  226. func GetJSON(url string, result interface{}) (*resty.Response, error) {
  227. client, err := CreateClient()
  228. if err != nil {
  229. return nil, err
  230. }
  231. if result != nil {
  232. return client.GetWithResult(url, result)
  233. }
  234. return client.Get(url)
  235. }
  236. // GetJSONWithBearerToken 便捷函数:使用Bearer Token发送GET请求
  237. func GetJSONWithBearerToken(token, url string, result interface{}) (*resty.Response, error) {
  238. client, err := CreateClient()
  239. if err != nil {
  240. return nil, err
  241. }
  242. return client.GetWithAuth(url, token, result)
  243. }
  244. // GetJSONWithBasicAuth 便捷函数:使用Basic认证发送GET请求
  245. func GetJSONWithBasicAuth(username, password, url string, result interface{}) (*resty.Response, error) {
  246. client, err := CreateClient()
  247. if err != nil {
  248. return nil, err
  249. }
  250. // 为这个特定请求设置Basic Auth
  251. req := client.client.R()
  252. if username != "" && password != "" {
  253. auth := username + ":" + password
  254. token := base64.StdEncoding.EncodeToString([]byte(auth))
  255. req.SetHeader("Authorization", "Basic "+token)
  256. }
  257. if result != nil {
  258. req.SetResult(result)
  259. }
  260. return req.Get(url)
  261. }