feat: 从黄果 NET hgdjnet-server 9bfbafe 导入 HKDJ 官网后端
来源:hgdjnet-server 9bfbafe10d417deea959bd53117bc88a10e60a83 项目身份 HKDJ / JHA-216,独立官网仓库,Jenkins 守卫键 hkdjnet 测试目录 /server/hkdj_net,App/Web API 30331/30332 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
var _client *http.Client
|
||||
|
||||
func GetHttpClient() *http.Client {
|
||||
once.Do(func() {
|
||||
_client = &http.Client{
|
||||
Timeout: time.Minute * 1, //设置超时时间
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
TLSHandshakeTimeout: 10 * time.Second, //限制 TLS握手的时间
|
||||
ResponseHeaderTimeout: 60 * time.Second, //限制读取response header的时间,默认 timeout + 5*time.Second
|
||||
ExpectContinueTimeout: 1 * time.Second, //限制client在发送包含 Expect: 100-continue的header到收到继续发送body的response之间的时间等待。
|
||||
MaxIdleConns: 100, //所有host的连接池最大连接数量,默认无穷大
|
||||
MaxIdleConnsPerHost: 300, //每个host的连接池最大空闲连接数,默认2
|
||||
MaxConnsPerHost: 100, //每个host的最大连接数量
|
||||
IdleConnTimeout: 3 * time.Minute, //how long an idle connection is kept in the connection pool.
|
||||
},
|
||||
}
|
||||
})
|
||||
return _client
|
||||
}
|
||||
|
||||
func getBytes(request interface{}) ([]byte, error) {
|
||||
var body []byte
|
||||
switch t := request.(type) {
|
||||
case []byte:
|
||||
body = t
|
||||
case string:
|
||||
body = []byte(t)
|
||||
default:
|
||||
var err error
|
||||
body, err = json.Marshal(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type OnHttpResponse func(res *http.Response) error
|
||||
|
||||
func HttpRequest(req *http.Request, onResponse OnHttpResponse) error {
|
||||
client := GetHttpClient()
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if onResponse != nil {
|
||||
err = onResponse(res)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func HttpMethod(url, method string, header http.Header, body io.Reader, onResponse OnHttpResponse) error {
|
||||
req, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if header != nil {
|
||||
req.Header = header
|
||||
}
|
||||
return HttpRequest(req, onResponse)
|
||||
}
|
||||
|
||||
func HttpGet(url string, header http.Header, body io.Reader, onResponse OnHttpResponse) error {
|
||||
return HttpMethod(url, http.MethodGet, header, body, onResponse)
|
||||
}
|
||||
|
||||
func HttpPost(url string, header http.Header, body io.Reader, onResponse OnHttpResponse) error {
|
||||
return HttpMethod(url, http.MethodPost, header, body, onResponse)
|
||||
}
|
||||
|
||||
func HttpDelete(url string, header http.Header, body io.Reader, onResponse OnHttpResponse) error {
|
||||
return HttpMethod(url, http.MethodDelete, header, body, onResponse)
|
||||
}
|
||||
|
||||
func HttpPostRequestJson(url string, request interface{}, resp interface{}) error {
|
||||
header := make(http.Header)
|
||||
header.Set("Content-Type", "application/json")
|
||||
body, err := getBytes(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return HttpPost(url, header, bytes.NewReader(body), func(res *http.Response) error {
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("http request (%s) error %s", url, res.Status)
|
||||
}
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(content, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func POSTJson(url string, headers map[string]string, data interface{}) (*http.Response, error) {
|
||||
header := make(http.Header)
|
||||
for k, v := range headers {
|
||||
header.Set(k, v)
|
||||
}
|
||||
body, err := getBytes(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = header
|
||||
client := GetHttpClient()
|
||||
return client.Do(req)
|
||||
}
|
||||
|
||||
func GetWithParam(url string, headers map[string]string, params ...interface{}) (*http.Response, error) {
|
||||
header := make(http.Header)
|
||||
for k, v := range headers {
|
||||
header.Set(k, v)
|
||||
}
|
||||
for _, p := range params {
|
||||
url = addParams(url, toUrlValues(p))
|
||||
}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = header
|
||||
client := GetHttpClient()
|
||||
return client.Do(req)
|
||||
}
|
||||
|
||||
func GetWithJResp(bind interface{}, url string, headers map[string]string, params ...interface{}) (int, error) {
|
||||
header := make(http.Header)
|
||||
for k, v := range headers {
|
||||
header.Set(k, v)
|
||||
}
|
||||
for _, p := range params {
|
||||
url = addParams(url, toUrlValues(p))
|
||||
}
|
||||
code := http.StatusBadRequest
|
||||
err := HttpGet(url, header, nil, func(res *http.Response) error {
|
||||
code = res.StatusCode
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("http request (%s) error %s", url, res.Status)
|
||||
}
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(content, bind)
|
||||
})
|
||||
return code, err
|
||||
}
|
||||
|
||||
func POSTWithJResp(bind interface{}, url string, headers map[string]string, params interface{}) (int, error) {
|
||||
header := make(http.Header)
|
||||
for k, v := range headers {
|
||||
header.Set(k, v)
|
||||
}
|
||||
body, err := getBytes(params)
|
||||
if err != nil {
|
||||
return http.StatusBadRequest, err
|
||||
}
|
||||
code := http.StatusBadRequest
|
||||
err = HttpPost(url, header, bytes.NewReader(body), func(res *http.Response) error {
|
||||
code = res.StatusCode
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("http request (%s) error %s", url, res.Status)
|
||||
}
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(content, bind)
|
||||
})
|
||||
return code, err
|
||||
}
|
||||
|
||||
func POSTJsonWithJResp(bind interface{}, url string, headers map[string]string, data interface{}) (int, error) {
|
||||
header := make(http.Header)
|
||||
for k, v := range headers {
|
||||
header.Set(k, v)
|
||||
}
|
||||
header.Set("Content-Type", "application/json")
|
||||
body, err := getBytes(data)
|
||||
if err != nil {
|
||||
return http.StatusBadRequest, err
|
||||
}
|
||||
code := http.StatusBadRequest
|
||||
err = HttpPost(url, header, bytes.NewReader(body), func(res *http.Response) error {
|
||||
code = res.StatusCode
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("http request (%s) error %s", url, res.Status)
|
||||
}
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(content, bind)
|
||||
})
|
||||
return code, err
|
||||
}
|
||||
|
||||
func DeleteWithJResp(bind interface{}, url string, headers map[string]string, params interface{}) (int, error) {
|
||||
header := make(http.Header)
|
||||
for k, v := range headers {
|
||||
header.Set(k, v)
|
||||
}
|
||||
body, err := getBytes(params)
|
||||
if err != nil {
|
||||
return http.StatusBadRequest, err
|
||||
}
|
||||
code := http.StatusBadRequest
|
||||
err = HttpDelete(url, header, bytes.NewReader(body), func(res *http.Response) error {
|
||||
code = res.StatusCode
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("http request (%s) error %s", url, res.Status)
|
||||
}
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(content, bind)
|
||||
})
|
||||
return code, err
|
||||
}
|
||||
|
||||
// Add params to a url string.
|
||||
func addParams(url_ string, params url.Values) string {
|
||||
if len(params) == 0 {
|
||||
return url_
|
||||
}
|
||||
|
||||
if !strings.Contains(url_, "?") {
|
||||
url_ += "?"
|
||||
}
|
||||
|
||||
if strings.HasSuffix(url_, "?") || strings.HasSuffix(url_, "&") {
|
||||
url_ += params.Encode()
|
||||
} else {
|
||||
url_ += "&" + params.Encode()
|
||||
}
|
||||
|
||||
return url_
|
||||
}
|
||||
|
||||
func toUrlValues(v interface{}) url.Values {
|
||||
switch t := v.(type) {
|
||||
case url.Values:
|
||||
return t
|
||||
case map[string][]string:
|
||||
return url.Values(t)
|
||||
case map[string]string:
|
||||
rst := make(url.Values)
|
||||
for k, v := range t {
|
||||
rst.Add(k, v)
|
||||
}
|
||||
return rst
|
||||
case nil:
|
||||
return make(url.Values)
|
||||
default:
|
||||
panic("Invalid value")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user