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

232 lines
6.0 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. res, err := ioutil.ReadAll(resp.Body)
  76. if CurlDebug {
  77. blob := SerializeStr(body)
  78. if contentType != "application/json" {
  79. blob = HttpBuild(body)
  80. }
  81. 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",
  82. router,
  83. time.Now().Format("2006-01-02 15:04:05.000"),
  84. method,
  85. contentType,
  86. HttpBuildQuery(header),
  87. blob,
  88. err,
  89. SerializeStr(resp.Header),
  90. string(res),
  91. )
  92. }
  93. resp.Body.Close()
  94. return res, err
  95. }
  96. func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) {
  97. var reqBody io.Reader
  98. contentType := "application/json"
  99. if header == nil {
  100. header = map[string]string{"Content-Type": contentType}
  101. }
  102. if _, ok := header["Content-Type"]; !ok {
  103. header["Content-Type"] = contentType
  104. }
  105. resp, er := CurlReq(method, router, reqBody, header)
  106. if er != nil {
  107. return nil, er
  108. }
  109. res, err := ioutil.ReadAll(resp.Body)
  110. if CurlDebug {
  111. blob := SerializeStr(body)
  112. if contentType != "application/json" {
  113. blob = HttpBuild(body)
  114. }
  115. 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",
  116. router,
  117. time.Now().Format("2006-01-02 15:04:05.000"),
  118. method,
  119. contentType,
  120. HttpBuildQuery(header),
  121. blob,
  122. err,
  123. SerializeStr(resp.Header),
  124. string(res),
  125. )
  126. }
  127. resp.Body.Close()
  128. return res, err
  129. }
  130. func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) {
  131. req, _ := http.NewRequest(method, router, reqBody)
  132. if header != nil {
  133. for k, v := range header {
  134. req.Header.Set(k, v)
  135. }
  136. }
  137. // 绕过github等可能因为特征码返回503问题
  138. // https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/
  139. defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009,
  140. 0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a}
  141. client := &http.Client{
  142. Transport: &http.Transport{
  143. TLSClientConfig: &tls.Config{
  144. InsecureSkipVerify: true,
  145. CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...),
  146. },
  147. },
  148. // 获取301重定向
  149. CheckRedirect: func(req *http.Request, via []*http.Request) error {
  150. return http.ErrUseLastResponse
  151. },
  152. }
  153. return client.Do(req)
  154. }
  155. // 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321
  156. func HttpBuildQuery(args map[string]string, sortAsc ...bool) string {
  157. str := ""
  158. if len(args) == 0 {
  159. return str
  160. }
  161. if len(sortAsc) > 0 {
  162. keys := make([]string, 0, len(args))
  163. for k := range args {
  164. keys = append(keys, k)
  165. }
  166. if sortAsc[0] {
  167. sort.Strings(keys)
  168. } else {
  169. sort.Sort(sort.Reverse(sort.StringSlice(keys)))
  170. }
  171. for _, k := range keys {
  172. str += "&" + k + "=" + args[k]
  173. }
  174. } else {
  175. for k, v := range args {
  176. str += "&" + k + "=" + v
  177. }
  178. }
  179. return str[1:]
  180. }
  181. func HttpBuild(body interface{}, sortAsc ...bool) string {
  182. params := map[string]string{}
  183. if args, ok := body.(map[string]interface{}); 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]string); ok {
  190. for k, v := range args {
  191. params[k] = AnyToString(v)
  192. }
  193. return HttpBuildQuery(params, sortAsc...)
  194. }
  195. if args, ok := body.(map[string]int); ok {
  196. for k, v := range args {
  197. params[k] = AnyToString(v)
  198. }
  199. return HttpBuildQuery(params, sortAsc...)
  200. }
  201. return AnyToString(body)
  202. }
  203. func convertToString(v interface{}) string {
  204. if v == nil {
  205. return ""
  206. }
  207. var (
  208. bs []byte
  209. err error
  210. )
  211. if bs, err = json.Marshal(v); err != nil {
  212. return ""
  213. }
  214. str := string(bs)
  215. return str
  216. }