golang-im聊天
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

curl.go 5.7 KiB

2年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. package utils
  2. import (
  3. "bytes"
  4. "crypto/tls"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "net/http"
  9. "net/url"
  10. "sort"
  11. "strings"
  12. "time"
  13. )
  14. var CurlDebug bool
  15. func CurlGet(router string, header map[string]string) ([]byte, error) {
  16. return curl(http.MethodGet, router, nil, header)
  17. }
  18. func CurlGetJson(router string, body interface{}, header map[string]string) ([]byte, error) {
  19. return curl_new(http.MethodGet, router, body, header)
  20. }
  21. // 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
  22. func CurlPost(router string, body interface{}, header map[string]string) ([]byte, error) {
  23. return curl(http.MethodPost, router, body, header)
  24. }
  25. func CurlPut(router string, body interface{}, header map[string]string) ([]byte, error) {
  26. return curl(http.MethodPut, router, body, header)
  27. }
  28. // 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
  29. func CurlPatch(router string, body interface{}, header map[string]string) ([]byte, error) {
  30. return curl(http.MethodPatch, router, body, header)
  31. }
  32. // CurlDelete is curl delete
  33. func CurlDelete(router string, body interface{}, header map[string]string) ([]byte, error) {
  34. return curl(http.MethodDelete, router, body, header)
  35. }
  36. func curl(method, router string, body interface{}, header map[string]string) ([]byte, error) {
  37. var reqBody io.Reader
  38. contentType := "application/json"
  39. switch v := body.(type) {
  40. case string:
  41. reqBody = strings.NewReader(v)
  42. case []byte:
  43. reqBody = bytes.NewReader(v)
  44. case map[string]string:
  45. val := url.Values{}
  46. for k, v := range v {
  47. val.Set(k, v)
  48. }
  49. reqBody = strings.NewReader(val.Encode())
  50. contentType = "application/x-www-form-urlencoded"
  51. case map[string]interface{}:
  52. val := url.Values{}
  53. for k, v := range v {
  54. val.Set(k, v.(string))
  55. }
  56. reqBody = strings.NewReader(val.Encode())
  57. contentType = "application/x-www-form-urlencoded"
  58. }
  59. if header == nil {
  60. header = map[string]string{"Content-Type": contentType}
  61. }
  62. if _, ok := header["Content-Type"]; !ok {
  63. header["Content-Type"] = contentType
  64. }
  65. resp, er := CurlReq(method, router, reqBody, header)
  66. if er != nil {
  67. return nil, er
  68. }
  69. res, err := ioutil.ReadAll(resp.Body)
  70. if CurlDebug {
  71. blob := SerializeStr(body)
  72. if contentType != "application/json" {
  73. blob = HttpBuild(body)
  74. }
  75. fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
  76. router,
  77. time.Now().Format("2006-01-02 15:04:05.000"),
  78. method,
  79. contentType,
  80. HttpBuildQuery(header),
  81. blob,
  82. err,
  83. SerializeStr(resp.Header),
  84. string(res),
  85. )
  86. }
  87. resp.Body.Close()
  88. return res, err
  89. }
  90. func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) {
  91. var reqBody io.Reader
  92. contentType := "application/json"
  93. if header == nil {
  94. header = map[string]string{"Content-Type": contentType}
  95. }
  96. if _, ok := header["Content-Type"]; !ok {
  97. header["Content-Type"] = contentType
  98. }
  99. resp, er := CurlReq(method, router, reqBody, header)
  100. if er != nil {
  101. return nil, er
  102. }
  103. res, err := ioutil.ReadAll(resp.Body)
  104. if CurlDebug {
  105. blob := SerializeStr(body)
  106. if contentType != "application/json" {
  107. blob = HttpBuild(body)
  108. }
  109. fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
  110. router,
  111. time.Now().Format("2006-01-02 15:04:05.000"),
  112. method,
  113. contentType,
  114. HttpBuildQuery(header),
  115. blob,
  116. err,
  117. SerializeStr(resp.Header),
  118. string(res),
  119. )
  120. }
  121. resp.Body.Close()
  122. return res, err
  123. }
  124. func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) {
  125. req, _ := http.NewRequest(method, router, reqBody)
  126. if header != nil {
  127. for k, v := range header {
  128. req.Header.Set(k, v)
  129. }
  130. }
  131. // 绕过github等可能因为特征码返回503问题
  132. // https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/
  133. defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009,
  134. 0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a}
  135. client := &http.Client{
  136. Transport: &http.Transport{
  137. TLSClientConfig: &tls.Config{
  138. InsecureSkipVerify: true,
  139. CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...),
  140. },
  141. },
  142. // 获取301重定向
  143. CheckRedirect: func(req *http.Request, via []*http.Request) error {
  144. return http.ErrUseLastResponse
  145. },
  146. }
  147. return client.Do(req)
  148. }
  149. // 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321
  150. func HttpBuildQuery(args map[string]string, sortAsc ...bool) string {
  151. str := ""
  152. if len(args) == 0 {
  153. return str
  154. }
  155. if len(sortAsc) > 0 {
  156. keys := make([]string, 0, len(args))
  157. for k := range args {
  158. keys = append(keys, k)
  159. }
  160. if sortAsc[0] {
  161. sort.Strings(keys)
  162. } else {
  163. sort.Sort(sort.Reverse(sort.StringSlice(keys)))
  164. }
  165. for _, k := range keys {
  166. str += "&" + k + "=" + args[k]
  167. }
  168. } else {
  169. for k, v := range args {
  170. str += "&" + k + "=" + v
  171. }
  172. }
  173. return str[1:]
  174. }
  175. func HttpBuild(body interface{}, sortAsc ...bool) string {
  176. params := map[string]string{}
  177. if args, ok := body.(map[string]interface{}); ok {
  178. for k, v := range args {
  179. params[k] = AnyToString(v)
  180. }
  181. return HttpBuildQuery(params, sortAsc...)
  182. }
  183. if args, ok := body.(map[string]string); ok {
  184. for k, v := range args {
  185. params[k] = AnyToString(v)
  186. }
  187. return HttpBuildQuery(params, sortAsc...)
  188. }
  189. if args, ok := body.(map[string]int); ok {
  190. for k, v := range args {
  191. params[k] = AnyToString(v)
  192. }
  193. return HttpBuildQuery(params, sortAsc...)
  194. }
  195. return AnyToString(body)
  196. }