package httputil import ( "context" "encoding/json" "fmt" "io" "net/http" "net/url" "strings" ) func ClientGet(connTimeout int, url string, headers map[string]string, params ...any) (*http.Response, error) { for _, p := range params { url = addParams(url, toUrlValues(p)) } req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, err } for k, v := range headers { req.Header.Set(k, v) } cl := getClientByTimeoutSet(connTimeout) return cl.Do(req) } func DefaultClientGet(url string, headers map[string]string, params ...any) (*http.Response, error) { return ClientGet(defaultTimeOut, url, headers, params...) } func ClientGetBytes(connTimeout int, url string, headers map[string]string, params ...any) (int, []byte, error) { resp, err := ClientGet(connTimeout, url, headers, params...) if err != nil { return 0, nil, err } ct, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil { return resp.StatusCode, nil, err } return resp.StatusCode, ct, nil } func DefaultClientGetBytes(url string, headers map[string]string, params ...any) (int, []byte, error) { return ClientGetBytes(defaultTimeOut, url, headers, params...) } func ClientGetBytesWithProxy(connTimeout int, p *ProxyCfg, url string, headers map[string]string, params ...any) (int, []byte, error) { if p == nil { return 0, nil, errProxyNil } pUrl, pHeaders, err := p.Build(url, headers) if err != nil { return 0, nil, err } return ClientGetBytes(connTimeout, pUrl, pHeaders, params...) } func ClientGetWithRespWithProxy(connTimeout int, p *ProxyCfg, bind any, url string, headers map[string]string, params ...any) (int, error) { code, bts, err := ClientGetBytesWithProxy(connTimeout, p, url, headers, params...) if err != nil { return code, err } return code, json.Unmarshal(bts, &bind) } func DefaultClientGetWithRespWithProxy(p *ProxyCfg, bind any, url string, headers map[string]string, params ...any) (int, error) { return ClientGetWithRespWithProxy(defaultTimeOut, p, bind, url, headers, params...) } func ClientGetWithResp(bind any, connTimeout int, url string, headers map[string]string, params ...any) (int, error) { code, ct, err := ClientGetBytes(connTimeout, url, headers, params...) if err != nil { return code, err } return code, json.Unmarshal(ct, &bind) } func DefaultClientGetWithResp(bind any, url string, headers map[string]string, params ...any) (int, error) { return ClientGetWithResp(bind, defaultTimeOut, url, headers, params...) } func ClientGetWithRespWithCtx(ctx context.Context, bind any, connTimeout int, url string, headers map[string]string, params ...any) (int, error) { code, ct, err := ClientGetBytesWithCtx(ctx, connTimeout, url, headers, params...) if err != nil { return code, err } return code, json.Unmarshal(ct, &bind) } func DefaultClientGetWithRespWithCtx(ctx context.Context, bind any, url string, headers map[string]string, params ...any) (int, error) { code, ct, err := ClientGetBytesWithCtx(ctx, defaultTimeOut, url, headers, params...) if err != nil { return code, err } return code, json.Unmarshal(ct, &bind) } func ClientGetWithCtx(ctx context.Context, connTimeout int, url string, headers map[string]string, params ...any) (*http.Response, error) { for _, p := range params { url = addParams(url, toUrlValues(p)) } req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, err } for k, v := range headers { req.Header.Add(k, v) } req = req.WithContext(ctx) cl := getClientByTimeoutSet(connTimeout) return cl.Do(req) } func DefaultClientGetWithCtx(ctx context.Context, url string, headers map[string]string, params ...any) (*http.Response, error) { return ClientGetWithCtx(ctx, defaultTimeOut, url, headers, params...) } func ClientGetBytesWithCtx(ctx context.Context, connTimeout int, url string, headers map[string]string, params ...any) (int, []byte, error) { resp, err := ClientGetWithCtx(ctx, connTimeout, url, headers, params...) if err != nil { return 0, nil, err } ct, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil { return resp.StatusCode, nil, err } return resp.StatusCode, ct, nil } func DefaultClientGetBytesWithCtx(ctx context.Context, url string, headers map[string]string, params ...any) (int, []byte, error) { return ClientGetBytesWithCtx(ctx, defaultTimeOut, url, headers, params...) } 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 map[string]interface{}: rst := make(url.Values) for k, v := range t { rst.Add(k, fmt.Sprintf("%v", v)) } return rst case nil: return make(url.Values) default: panic("Invalid value") } } 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_ }