client.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package request
  2. import (
  3. "crypto/tls"
  4. "io"
  5. "net"
  6. "net/http"
  7. "net/http/cookiejar"
  8. "strings"
  9. "time"
  10. )
  11. type (
  12. BeforeRequest func(req *http.Request) (err error)
  13. AfterRequest func(req *http.Request, res *http.Response) (err error)
  14. Client struct {
  15. baseUrl string
  16. Authorization Authorization
  17. client *http.Client
  18. cookieJar *cookiejar.Jar
  19. interceptorRequest []BeforeRequest
  20. interceptorResponse []AfterRequest
  21. }
  22. )
  23. var (
  24. DefaultClient = &http.Client{
  25. Transport: &http.Transport{
  26. Proxy: http.ProxyFromEnvironment,
  27. ForceAttemptHTTP2: true,
  28. MaxIdleConns: 64,
  29. MaxIdleConnsPerHost: 8,
  30. IdleConnTimeout: 90 * time.Second,
  31. TLSHandshakeTimeout: 10 * time.Second,
  32. ExpectContinueTimeout: 1 * time.Second,
  33. TLSClientConfig: &tls.Config{
  34. InsecureSkipVerify: true,
  35. },
  36. },
  37. Timeout: time.Second * 30,
  38. }
  39. UnsafeClient = &http.Client{
  40. Transport: &http.Transport{
  41. Proxy: http.ProxyFromEnvironment,
  42. ForceAttemptHTTP2: true,
  43. DialContext: (&net.Dialer{
  44. Timeout: 30 * time.Second,
  45. KeepAlive: 30 * time.Second,
  46. }).DialContext,
  47. MaxIdleConns: 64,
  48. MaxIdleConnsPerHost: 8,
  49. IdleConnTimeout: 90 * time.Second,
  50. TLSHandshakeTimeout: 10 * time.Second,
  51. ExpectContinueTimeout: 1 * time.Second,
  52. TLSClientConfig: &tls.Config{
  53. InsecureSkipVerify: true,
  54. },
  55. },
  56. Timeout: time.Second * 30,
  57. }
  58. )
  59. func (client *Client) stashUri(urlPath string) string {
  60. var (
  61. pos int
  62. )
  63. if len(urlPath) == 0 {
  64. return client.baseUrl
  65. }
  66. if pos = strings.Index(urlPath, "//"); pos == -1 {
  67. if client.baseUrl != "" {
  68. if urlPath[0] != '/' {
  69. urlPath = "/" + urlPath
  70. }
  71. return client.baseUrl + urlPath
  72. }
  73. }
  74. return urlPath
  75. }
  76. func (client *Client) BeforeRequest(cb BeforeRequest) *Client {
  77. client.interceptorRequest = append(client.interceptorRequest, cb)
  78. return client
  79. }
  80. func (client *Client) AfterRequest(cb AfterRequest) *Client {
  81. client.interceptorResponse = append(client.interceptorResponse, cb)
  82. return client
  83. }
  84. func (client *Client) SetBaseUrl(s string) *Client {
  85. client.baseUrl = strings.TrimSuffix(s, "/")
  86. return client
  87. }
  88. func (client *Client) SetCookieJar(cookieJar *cookiejar.Jar) *Client {
  89. client.client.Jar = cookieJar
  90. return client
  91. }
  92. func (client *Client) SetClient(httpClient *http.Client) *Client {
  93. client.client = httpClient
  94. if client.cookieJar != nil {
  95. client.client.Jar = client.cookieJar
  96. }
  97. return client
  98. }
  99. func (client *Client) SetTransport(transport http.RoundTripper) *Client {
  100. client.client.Transport = transport
  101. return client
  102. }
  103. func (client *Client) Get(urlPath string) *Request {
  104. return newRequest(http.MethodGet, client.stashUri(urlPath), client)
  105. }
  106. func (client *Client) Put(urlPath string) *Request {
  107. return newRequest(http.MethodPut, client.stashUri(urlPath), client)
  108. }
  109. func (client *Client) Post(urlPath string) *Request {
  110. return newRequest(http.MethodPost, client.stashUri(urlPath), client)
  111. }
  112. func (client *Client) Delete(urlPath string) *Request {
  113. return newRequest(http.MethodDelete, client.stashUri(urlPath), client)
  114. }
  115. func (client *Client) execute(r *Request) (res *http.Response, err error) {
  116. var (
  117. n int
  118. reader io.Reader
  119. )
  120. if r.contentType == "" && r.body != nil {
  121. r.contentType = r.detectContentType(r.body)
  122. }
  123. if r.body != nil {
  124. if reader, err = r.readRequestBody(r.contentType, r.body); err != nil {
  125. return
  126. }
  127. }
  128. if r.rawRequest, err = http.NewRequest(r.method, r.uri, reader); err != nil {
  129. return
  130. }
  131. for k, vs := range r.header {
  132. for _, v := range vs {
  133. r.rawRequest.Header.Add(k, v)
  134. }
  135. }
  136. if r.contentType != "" {
  137. r.rawRequest.Header.Set("Content-Type", r.contentType)
  138. }
  139. if client.Authorization != nil {
  140. r.rawRequest.Header.Set("Authorization", client.Authorization.Token())
  141. }
  142. if r.context != nil {
  143. r.rawRequest = r.rawRequest.WithContext(r.context)
  144. }
  145. n = len(client.interceptorRequest)
  146. for i := n - 1; i >= 0; i-- {
  147. if err = client.interceptorRequest[i](r.rawRequest); err != nil {
  148. return
  149. }
  150. }
  151. if r.rawResponse, err = client.client.Do(r.rawRequest); err != nil {
  152. return nil, err
  153. }
  154. n = len(client.interceptorResponse)
  155. for i := n - 1; i >= 0; i-- {
  156. if err = client.interceptorResponse[i](r.rawRequest, r.rawResponse); err != nil {
  157. _ = r.rawResponse.Body.Close()
  158. return
  159. }
  160. }
  161. return r.rawResponse, err
  162. }
  163. func New() *Client {
  164. client := &Client{
  165. client: DefaultClient,
  166. interceptorRequest: make([]BeforeRequest, 0, 10),
  167. interceptorResponse: make([]AfterRequest, 0, 10),
  168. }
  169. client.cookieJar, _ = cookiejar.New(nil)
  170. client.client.Jar = client.cookieJar
  171. return client
  172. }