http_client.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package utils
  2. import (
  3. "bytes"
  4. "crypto/tls"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "net/http"
  9. "time"
  10. )
  11. // PostJSON 向指定 URL 发起 HTTPS POST 请求,支持自定义请求头和 JSON body。
  12. // 参数:
  13. // - url: 完整请求地址(支持 https)
  14. // - headers: 自定义请求头(可为 nil)
  15. // - body: 将被序列化为 JSON 的数据(可为 map/struct)
  16. // - timeout: 请求超时时间
  17. // - insecureSkipVerify: 是否跳过 TLS 证书校验(测试环境可设为 true)
  18. //
  19. // 返回值: HTTP 状态码、响应体字节、错误
  20. func PostJSON(url string, headers map[string]string, body interface{}, timeout time.Duration, insecureSkipVerify bool) (int, []byte, error) {
  21. // 序列化 body
  22. var buf bytes.Buffer
  23. if body != nil {
  24. enc := json.NewEncoder(&buf)
  25. if err := enc.Encode(body); err != nil {
  26. return 0, nil, fmt.Errorf("encode body to json: %w", err)
  27. }
  28. }
  29. // 自定义 transport 支持跳过证书校验
  30. tr := &http.Transport{
  31. TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify},
  32. }
  33. client := &http.Client{Transport: tr, Timeout: timeout}
  34. req, err := http.NewRequest(http.MethodPost, url, &buf)
  35. if err != nil {
  36. return 0, nil, fmt.Errorf("create request: %w", err)
  37. }
  38. // 默认 Content-Type 为 application/json
  39. req.Header.Set("Content-Type", "application/json")
  40. for k, v := range headers {
  41. if k == "Content-Type" {
  42. req.Header.Set(k, v)
  43. continue
  44. }
  45. req.Header.Set(k, v)
  46. }
  47. resp, err := client.Do(req)
  48. if err != nil {
  49. return 0, nil, fmt.Errorf("do request: %w", err)
  50. }
  51. defer resp.Body.Close()
  52. respBytes, err := io.ReadAll(resp.Body)
  53. if err != nil {
  54. return resp.StatusCode, nil, fmt.Errorf("read response: %w", err)
  55. }
  56. return resp.StatusCode, respBytes, nil
  57. }
  58. // PostJSONDefault 简化版,使用 10s 超时且默认验证证书
  59. func PostJSONDefault(url string, headers map[string]string, body interface{}) (int, []byte, error) {
  60. return PostJSON(url, headers, body, 10*time.Second, false)
  61. }