diff --git a/netutil/httpreq/client.go b/netutil/httpreq/client.go index a810eee61..d5a0657ce 100644 --- a/netutil/httpreq/client.go +++ b/netutil/httpreq/client.go @@ -3,10 +3,8 @@ package httpreq import ( "bytes" - "encoding/json" "io" "net/http" - "net/url" "strings" "time" @@ -57,6 +55,9 @@ func ConfigStd(fn func(hc *http.Client)) { fn(std.client.(*http.Client)) } +// Std instance +func Std() *ReqClient { return std } + // Get quick send a GET request by default client func Get(url string, opt *ReqOption) (*http.Response, error) { return std.Method(http.MethodGet).SendWithOpt(url, opt) @@ -155,36 +156,7 @@ func (h *ReqClient) StringBody(s string) *ReqClient { // Allow type: // - string, []byte, map[string][]string/url.Values, io.Reader(eg: bytes.Buffer, strings.Reader) func (h *ReqClient) AnyBody(data any) *ReqClient { - var reqBody io.Reader - switch typBody := data.(type) { - case io.Reader: - reqBody = typBody - case map[string][]string: - reqBody = bytes.NewBufferString(url.Values(typBody).Encode()) - case url.Values: - reqBody = bytes.NewBufferString(typBody.Encode()) - case string: - reqBody = bytes.NewBufferString(typBody) - case []byte: - reqBody = bytes.NewBuffer(typBody) - default: - // auto encode body data to json - if data != nil { - buf := &bytes.Buffer{} - enc := json.NewEncoder(buf) - // close escape &, <, > TO \u0026, \u003c, \u003e - enc.SetEscapeHTML(false) - if err := enc.Encode(data); err != nil { - panic("auto encode data error=" + err.Error()) - } - - reqBody = buf - } - - // nobody - } - - h.body = reqBody + h.body = ToRequestBody(data) return h } @@ -211,17 +183,7 @@ func (h *ReqClient) Send(url string) (*http.Response, error) { // SendWithOpt request and return http response func (h *ReqClient) SendWithOpt(url string, opt *ReqOption) (*http.Response, error) { - if opt == nil { - opt = emptyOpt - } - cli := h - if opt.Timeout > 0 { - cli = New().Client(&http.Client{ - Timeout: time.Duration(opt.Timeout) * time.Millisecond, - }) - } - if len(cli.baseURL) > 0 { if !strings.HasPrefix(url, "http") { url = cli.baseURL + url @@ -235,6 +197,21 @@ func (h *ReqClient) SendWithOpt(url string, opt *ReqOption) (*http.Response, err if err != nil { return nil, err } + return h.SendRequest(req, opt) +} + +// SendRequest request and return http response +func (h *ReqClient) SendRequest(req *http.Request, opt *ReqOption) (*http.Response, error) { + if opt == nil { + opt = emptyOpt + } + + cli := h + if opt.Timeout > 0 { + cli = New().Client(&http.Client{ + Timeout: time.Duration(opt.Timeout) * time.Millisecond, + }) + } if len(cli.headerMap) > 0 { for k, v := range cli.headerMap { diff --git a/netutil/httpreq/util.go b/netutil/httpreq/util.go index df36a783b..9e3ec7d79 100644 --- a/netutil/httpreq/util.go +++ b/netutil/httpreq/util.go @@ -3,6 +3,8 @@ package httpreq import ( "bytes" "encoding/base64" + "encoding/json" + "io" "net/http" "net/url" "strings" @@ -65,6 +67,13 @@ func AddHeaders(req *http.Request, header http.Header) { } } +// AddHeaderMap to reqeust instance. +func AddHeaderMap(req *http.Request, headerMap map[string]string) { + for k, v := range headerMap { + req.Header.Set(k, v) + } +} + // HeaderToStringMap convert func HeaderToStringMap(rh http.Header) map[string]string { if len(rh) == 0 { @@ -99,6 +108,54 @@ func ToQueryValues(data any) url.Values { return uv } +// IsNoBodyMethod check +func IsNoBodyMethod(method string) bool { + return method != "POST" && method != "PUT" && method != "PATCH" +} + +// ToRequestBody convert handle +// +// Allow type for data: +// - string +// - []byte +// - map[string]string +// - map[string][]string/url.Values +// - io.Reader(eg: bytes.Buffer, strings.Reader) +func ToRequestBody(data any) io.Reader { + var reqBody io.Reader + switch typVal := data.(type) { + case io.Reader: + reqBody = typVal + case map[string]string: + reqBody = bytes.NewBufferString(ToQueryValues(typVal).Encode()) + case map[string][]string: + reqBody = bytes.NewBufferString(url.Values(typVal).Encode()) + case url.Values: + reqBody = bytes.NewBufferString(typVal.Encode()) + case string: + reqBody = bytes.NewBufferString(typVal) + case []byte: + reqBody = bytes.NewBuffer(typVal) + default: + // auto encode body data to json + if data != nil { + buf := &bytes.Buffer{} + enc := json.NewEncoder(buf) + // close escape &, <, > TO \u0026, \u003c, \u003e + enc.SetEscapeHTML(false) + if err := enc.Encode(data); err != nil { + panic("auto encode data error=" + err.Error()) + } + + reqBody = buf + } + + // nobody + } + + return reqBody +} + // RequestToString convert http Request to string func RequestToString(r *http.Request) string { buf := &bytes.Buffer{}