forked from all_user/stat_center
Initial commit
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
package httputil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"stat/common/log"
|
||||
"strconv"
|
||||
|
||||
"github.com/ddliu/go-httpclient"
|
||||
)
|
||||
|
||||
//HTTPClient htttp客户端
|
||||
type HTTPClient struct {
|
||||
client *httpclient.HttpClient
|
||||
}
|
||||
|
||||
type ProxyCfg struct {
|
||||
Host string
|
||||
Timeout int //秒
|
||||
Source string
|
||||
IsActive bool //是否开启代理
|
||||
}
|
||||
|
||||
func NewHTTPClient(client *httpclient.HttpClient) *HTTPClient {
|
||||
return &HTTPClient{client}
|
||||
}
|
||||
|
||||
func (p *ProxyCfg) Build(rawurl string, rawHeaders map[string]string) (string, map[string]string, error) {
|
||||
if !p.IsActive {
|
||||
return rawurl, rawHeaders, nil
|
||||
}
|
||||
u, err := url.Parse(rawurl)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
target := url.URL{Scheme: u.Scheme, Host: u.Host}
|
||||
u.Host = p.Host
|
||||
u.Scheme = "http"
|
||||
m := make(map[string]string)
|
||||
m["X-Proxy-Target-Host"] = target.String()
|
||||
m["X-Proxy-Source"] = "ys"
|
||||
if p.Timeout > 0 {
|
||||
m["X-Proxy-Timeout"] = strconv.Itoa(p.Timeout)
|
||||
}
|
||||
if len(rawHeaders) > 0 {
|
||||
for k, v := range rawHeaders {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
return u.String(), m, nil
|
||||
}
|
||||
|
||||
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().Defaults(httpclient.Map{
|
||||
httpclient.OPT_CONNECTTIMEOUT: 5,
|
||||
httpclient.OPT_TIMEOUT: 60,
|
||||
})
|
||||
return &HTTPClient{client: h}
|
||||
}
|
||||
|
||||
func NewCtx(ctx context.Context) *HTTPClient {
|
||||
h := httpclient.NewHttpClient().WithOptions(httpclient.Map{
|
||||
httpclient.OPT_CONNECTTIMEOUT: 5,
|
||||
httpclient.OPT_TIMEOUT: 60,
|
||||
httpclient.OPT_CONTEXT: ctx,
|
||||
})
|
||||
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,
|
||||
httpclient.OPT_TIMEOUT: 60,
|
||||
})
|
||||
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_TIMEOUT, 60)
|
||||
httpCliPool.cliPool[cliID] = h
|
||||
return &HTTPClient{client: h}
|
||||
}
|
||||
return &HTTPClient{client: h}
|
||||
}
|
||||
|
||||
func jsonUnmarshalResp(bind interface{}, resp *HTTPResponse) error {
|
||||
defer func() { _ = resp.Body.Body.Close() }()
|
||||
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
|
||||
}
|
||||
data, err := response.ReadAll()
|
||||
if err != nil {
|
||||
log.ZapLog.Error("resp readAll errror", log.Any("Error", err))
|
||||
return data, err
|
||||
}
|
||||
defer func() {
|
||||
_ = response.Body.Close()
|
||||
}()
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
err = jsonUnmarshalResp(bind, resp)
|
||||
}
|
||||
return resp.StatusCode, err
|
||||
}
|
||||
|
||||
// POSTWithJResp 结果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
|
||||
}
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
err = jsonUnmarshalResp(bind, resp)
|
||||
}
|
||||
return resp.StatusCode, err
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package httputil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type ResponseInfo struct {
|
||||
Gzipped bool `json:"gzipped"`
|
||||
Method string `json:"method"`
|
||||
Origin string `json:"origin"`
|
||||
Useragent string `json:"user-agent"` // http://httpbin.org/user-agent
|
||||
Form map[string]string `json:"form"`
|
||||
Files map[string]string `json:"files"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
Cookies map[string]string `json:"cookies"`
|
||||
}
|
||||
|
||||
var info ResponseInfo
|
||||
|
||||
type Resport struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func Test_Get_Httpcli(t *testing.T) {
|
||||
client := Client()
|
||||
var headers = map[string]string{"auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVjZTJiNzNmZTI3Y2YyMmE4ZjQyMTVkMCIsInVzZXJOYW1lIjoidHVib2xpbmcxNjgiLCJpc0xvZ2luIjp0cnVlLCJsb2dpblRpbWUiOjE1NjQxNDYwNzI5MDUsImlhdCI6MTU2NDE0NjA3Mn0.VQICBk71KDITus83pZEq3C1y_WbKPZc0HUfmIm_eby8"}
|
||||
respo, err := client.Get("https://no5.xiexiaojia.com/appjmall/api/showCore/appShowList", headers)
|
||||
defer respo.Body.Body.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("%+v", err)
|
||||
}
|
||||
resport := Resport{}
|
||||
body, err := respo.Body.ReadAll()
|
||||
//反序列化
|
||||
err = json.Unmarshal(body, &resport)
|
||||
fmt.Println("response", resport)
|
||||
//案例获取数据
|
||||
fmt.Println("response comName:", resport.Data.([]interface{})[0].(map[string]interface{})["comName"])
|
||||
}
|
||||
|
||||
func Test_Post_Httpcli(t *testing.T) {
|
||||
client := Client()
|
||||
fmt.Println("http 客户端", client)
|
||||
var headers = map[string]string{"auth_token": "xxxxx"}
|
||||
var params = map[string]string{"userId": "5ce2b73fe27cf22a8f4215d0", "price": "5000", "count": "1", "commId": "5ce40e03e27cf22a8f4215d8",
|
||||
"comName": "日本ceruru.b 脐带血面膜保湿补水修复5片",
|
||||
"comImageCar": "http://oam.szbslhb.com/4,01fb06b4adf1.jpg",
|
||||
"attributeCar": "",
|
||||
}
|
||||
respo, err := client.Post("https://no5.xiexiaojia.com/appjmall/api/cart/addCommToCart", headers, params)
|
||||
defer respo.Body.Body.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("%+v", err)
|
||||
}
|
||||
resport := Resport{}
|
||||
body, err := respo.Body.ReadAll()
|
||||
if err != nil {
|
||||
res, _ := respo.Body.ToString()
|
||||
fmt.Println("response", res)
|
||||
return
|
||||
}
|
||||
//反序列化
|
||||
err = json.Unmarshal(body, &resport)
|
||||
fmt.Println("response", resport)
|
||||
}
|
||||
|
||||
func Test_PostJson_Httpcli(t *testing.T) {
|
||||
client := Client()
|
||||
var headers = map[string]string{"Content-Type": "application/json"}
|
||||
fmt.Println("http 客户端", client)
|
||||
respo, err := client.Get("https://www.kancloud.cn/cattong/go_command_tutorial/261347", headers)
|
||||
defer respo.Body.Body.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("%+v", err)
|
||||
}
|
||||
body, err := respo.Body.ToString()
|
||||
fmt.Println("response", body)
|
||||
}
|
||||
|
||||
func Test_PutFile_Httpcli(t *testing.T) {
|
||||
client := Client()
|
||||
file, err := os.Open("/Users/mac/Downloads/1567069549ABBQCTFC.mp4")
|
||||
info, _ := file.Stat()
|
||||
|
||||
var headers = map[string]string{
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Authorization": "bucketName=bucket-01;accessKey=FSd58ed59fccc16812903c37068de8969b;ttl=1h",
|
||||
"Content-Disposition": "fileName=test02.mp4;size=" + strconv.FormatInt(info.Size(), 10),
|
||||
"Signature": "9cea21bf95f235e7d9c5a70888cf742cfb9c946ed25aef8b70ce77c953ccbff0",
|
||||
}
|
||||
fmt.Println("http 客户端", client)
|
||||
respo, err := client.Put("http://localhost:8888/fs/api/uploadStream", headers, file)
|
||||
defer respo.Body.Body.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("%+v", err)
|
||||
}
|
||||
body, err := respo.Body.ToString()
|
||||
fmt.Println("response", body)
|
||||
}
|
||||
Reference in New Issue
Block a user