第三方api接口
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.

236 regels
6.2 KiB

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