283 lines
8.9 KiB
Go
283 lines
8.9 KiB
Go
package httputil
|
|
|
|
import (
|
|
"91porn-server/common/log"
|
|
"91porn-server/middleware/requestid"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/ddliu/go-httpclient"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
)
|
|
|
|
// HTTPClient htttp客户端
|
|
type HTTPClient struct {
|
|
client *httpclient.HttpClient
|
|
}
|
|
|
|
func NewHTTPClient(client *httpclient.HttpClient) *HTTPClient {
|
|
return &HTTPClient{client}
|
|
}
|
|
|
|
type httpClientPool struct {
|
|
cliPool map[string]*httpclient.HttpClient
|
|
poolSize int
|
|
offset int
|
|
}
|
|
|
|
// HTTPResponse http响应
|
|
type HTTPResponse struct {
|
|
StatusCode int `json:"statusCode"`
|
|
Body *httpclient.Response `json:"boby"`
|
|
}
|
|
|
|
var httpCliPool = httpClientPool{cliPool: map[string]*httpclient.HttpClient{}, poolSize: 50}
|
|
|
|
func New() *HTTPClient {
|
|
h := httpclient.NewHttpClient().WithOptions(httpclient.Map{
|
|
httpclient.OPT_CONNECTTIMEOUT: 5,
|
|
httpclient.OPT_TIMEOUT: 10,
|
|
})
|
|
return &HTTPClient{client: h}
|
|
}
|
|
|
|
func NewCtx(ctx context.Context) *HTTPClient {
|
|
reqID, _ := ctx.Value(requestid.ContextKey).(string)
|
|
h := httpclient.NewHttpClient().WithOptions(httpclient.Map{
|
|
httpclient.OPT_CONNECTTIMEOUT: 5,
|
|
httpclient.OPT_TIMEOUT: 10,
|
|
httpclient.OPT_CONTEXT: ctx,
|
|
}).WithHeader(requestid.HeaderKey, reqID)
|
|
|
|
return &HTTPClient{client: h.Begin()}
|
|
}
|
|
|
|
// GetHTTPClient 获取httpclient
|
|
func Client() *HTTPClient {
|
|
cliID := "CLIENT-ID-"
|
|
if len(httpCliPool.cliPool) < httpCliPool.poolSize {
|
|
h := httpclient.NewHttpClient().Defaults(httpclient.Map{
|
|
httpclient.OPT_CONNECTTIMEOUT: 5,
|
|
})
|
|
cliID = cliID + strconv.FormatInt(int64(len(httpCliPool.cliPool)+1), 10)
|
|
httpCliPool.cliPool[cliID] = h
|
|
httpCliPool.offset = httpCliPool.poolSize
|
|
return &HTTPClient{client: h}
|
|
}
|
|
if httpCliPool.offset == httpCliPool.poolSize+1 {
|
|
httpCliPool.offset = 1
|
|
}
|
|
cliID = cliID + strconv.FormatInt(int64(httpCliPool.offset), 10)
|
|
httpCliPool.offset = httpCliPool.offset + 1
|
|
h, ok := httpCliPool.cliPool[cliID]
|
|
if !ok || h == nil {
|
|
h = httpclient.NewHttpClient().WithOption(httpclient.OPT_CONNECTTIMEOUT, 10)
|
|
httpCliPool.cliPool[cliID] = h
|
|
return &HTTPClient{client: h}
|
|
}
|
|
return &HTTPClient{client: h}
|
|
}
|
|
|
|
func jsonUnmarshalResp(bind interface{}, resp *HTTPResponse) error {
|
|
if bind == nil { //传入空表示只执行 defer
|
|
return nil
|
|
}
|
|
b, err := resp.Body.ReadAll()
|
|
if err != nil {
|
|
log.Error("httputil jsonUnmarshalResp readall err", log.E(err))
|
|
return err
|
|
}
|
|
err = json.Unmarshal(b, bind)
|
|
if err != nil {
|
|
log.Error("httputil jsonUnmarshalResp Unmarshal err", log.E(err))
|
|
}
|
|
return err
|
|
}
|
|
|
|
// Get Get方法
|
|
func (h *HTTPClient) Get(url string, headers map[string]string, params ...interface{}) (*HTTPResponse, error) {
|
|
h.client.WithHeaders(headers)
|
|
response, err := h.client.Get(url, params...)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client Get method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
return &HTTPResponse{StatusCode: response.StatusCode, Body: response}, nil
|
|
}
|
|
|
|
func (h *HTTPClient) PGet(p *ProxyCfg, url string, headers map[string]string, params ...interface{}) (*HTTPResponse, error) {
|
|
purl, pheaders, err := p.Build(url, headers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return h.Get(purl, pheaders, params)
|
|
}
|
|
|
|
// Get GetBytes
|
|
func (h *HTTPClient) GetBytes(url string, headers map[string]string, params ...interface{}) ([]byte, error) {
|
|
h.client.WithHeaders(headers)
|
|
response, err := h.client.Get(url, params...)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client Get method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
if response.StatusCode != http.StatusOK {
|
|
log.Error("http client Get method status code not ok", log.Any("url", url), log.Any("headers", headers), log.Any("params", params), log.Any("res", response))
|
|
return nil, errors.New("http response satus code not ok statusCoe:" + response.Status)
|
|
}
|
|
data, err := response.ReadAll()
|
|
if err != nil {
|
|
log.ZapLog.Error("resp readAll errror", log.Any("Error", err))
|
|
return data, err
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
// GetWithJResp 结果json.Unmarshal到bind中
|
|
func (h *HTTPClient) GetWithJResp(bind interface{}, url string, headers map[string]string, params ...interface{}) (int, error) {
|
|
resp, err := h.Get(url, headers, params...)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer func() { _ = resp.Body.Body.Close() }()
|
|
if resp.StatusCode == http.StatusOK {
|
|
err = jsonUnmarshalResp(bind, resp)
|
|
}
|
|
return resp.StatusCode, err
|
|
}
|
|
|
|
func (h *HTTPClient) PGetWithJResp(p *ProxyCfg, bind interface{}, url string, headers map[string]string, params ...interface{}) (int, error) {
|
|
purl, pheaders, err := p.Build(url, headers)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return h.GetWithJResp(bind, purl, pheaders, params...)
|
|
}
|
|
|
|
// Post Post方法
|
|
func (h *HTTPClient) Post(url string, headers map[string]string, params interface{}) (*HTTPResponse, error) {
|
|
h.client.WithHeaders(headers)
|
|
response, err := h.client.Post(url, params)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client Post method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
return &HTTPResponse{StatusCode: response.StatusCode, Body: response}, nil
|
|
}
|
|
|
|
func (h *HTTPClient) PPost(p *ProxyCfg, bind interface{}, url string, headers map[string]string, params interface{}) (*HTTPResponse, error) {
|
|
purl, pheaders, err := p.Build(url, headers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return h.Post(purl, pheaders, params)
|
|
}
|
|
|
|
// POSTJson PostJson方法
|
|
func (h *HTTPClient) POSTJson(url string, headers map[string]string, data interface{}) (*HTTPResponse, error) {
|
|
h.client.WithHeaders(headers)
|
|
response, err := h.client.PostJson(url, data)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client POSTJson method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
return &HTTPResponse{StatusCode: response.StatusCode, Body: response}, nil
|
|
}
|
|
|
|
// POSTJson PostJson方法, bind json.Unmarshal
|
|
func (h *HTTPClient) POSTJsonWithJResp(bind interface{}, url string, headers map[string]string, data interface{}) (int, error) {
|
|
resp, err := h.POSTJson(url, headers, data)
|
|
if err != nil {
|
|
log.Error("POSTJsonWithResp err", log.E(err))
|
|
return 0, err
|
|
}
|
|
defer resp.Body.Body.Close()
|
|
if resp.StatusCode == http.StatusOK {
|
|
err = jsonUnmarshalResp(bind, resp)
|
|
}
|
|
return resp.StatusCode, err
|
|
}
|
|
|
|
func (h *HTTPClient) PPOSTJsonWithJResp(p *ProxyCfg, bind interface{}, url string, headers map[string]string, data interface{}) (int, error) {
|
|
if p == nil {
|
|
return 0, fmt.Errorf("ProxyCfg is nil")
|
|
}
|
|
purl, pheaders, err := p.Build(url, headers)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return h.POSTJsonWithJResp(bind, purl, pheaders, data)
|
|
}
|
|
|
|
// PostMultipart PostMultipart 上传文件
|
|
func (h *HTTPClient) PostMultipart(url string, headers map[string]string, params interface{}) (*HTTPResponse, error) {
|
|
h.client.WithHeaders(headers)
|
|
response, err := h.client.PostMultipart(url, params)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client PostMultipart method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
return &HTTPResponse{StatusCode: response.StatusCode, Body: response}, nil
|
|
}
|
|
|
|
// Put 流式传输 可用于上传文件
|
|
func (h *HTTPClient) Put(url string, headers map[string]string, body io.Reader) (*HTTPResponse, error) {
|
|
h.client.WithHeaders(headers)
|
|
response, err := h.client.Put(url, body)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client PostMultipart method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
return &HTTPResponse{StatusCode: response.StatusCode, Body: response}, nil
|
|
}
|
|
|
|
// PutJSON PutJSON方法
|
|
func (h *HTTPClient) PutJSON(url string, headers map[string]string, data interface{}) (*HTTPResponse, error) {
|
|
h.client.WithHeaders(headers)
|
|
response, err := h.client.PutJson(url, data)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client PostMultipart method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
return &HTTPResponse{StatusCode: response.StatusCode, Body: response}, nil
|
|
}
|
|
|
|
// Header Header
|
|
func (h *HTTPClient) Header(url string) (*HTTPResponse, error) {
|
|
response, err := h.client.Head(url)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("http client PostMultipart method failed %+v:", err))
|
|
return nil, err
|
|
}
|
|
return &HTTPResponse{StatusCode: response.StatusCode, Body: response}, nil
|
|
}
|
|
|
|
// POSTWithJResp 结果json.Unmarshal到bind中 用于上传文件, content-type :"application/x-www-form-urlencoded" 如参数以@开头 则为上传文件
|
|
func (h *HTTPClient) POSTWithJResp(bind interface{}, url string, headers map[string]string, params interface{}) (int, error) {
|
|
resp, err := h.Post(url, headers, params)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer resp.Body.Body.Close()
|
|
if resp.StatusCode == http.StatusOK {
|
|
err = jsonUnmarshalResp(bind, resp)
|
|
}
|
|
return resp.StatusCode, err
|
|
}
|
|
|
|
// PPOSTWithJResp 结果json.Unmarshal到bind中 用于上传文件, content-type :"application/x-www-form-urlencoded" 如参数以@开头 则为上传文件
|
|
func (h *HTTPClient) PPOSTWithJResp(p *ProxyCfg, bind interface{}, url string, headers map[string]string, params interface{}) (int, error) {
|
|
resp, err := h.PPost(p, bind, url, headers, params)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer resp.Body.Body.Close()
|
|
if resp.StatusCode == http.StatusOK {
|
|
err = jsonUnmarshalResp(bind, resp)
|
|
}
|
|
return resp.StatusCode, err
|
|
}
|