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

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