1 Star 0 Fork 0

余济舟/aid

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
http_client.go 8.31 KB
一键复制 编辑 原始数据 按行查看 历史
余济舟 提交于 2025-09-03 11:48 +08:00 . [optimize]优化httpClientV2
package httpClientV2
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"encoding/xml"
"errors"
"io"
"net/http"
"net/url"
"sync"
"time"
"gitee.com/jericho-yu/aid/operation"
"gitee.com/jericho-yu/aid/str"
jsonIter "github.com/json-iterator/go"
"github.com/spf13/cast"
)
type (
HttpClient struct {
err error
url string
queries map[string]any
method string
headers map[string][]string
requestBody, responseBody []byte
timeout time.Duration
transport *http.Transport
cert []byte
rawRequest *http.Request
rawResponse *http.Response
client *http.Client
autoCopy bool
lock sync.RWMutex
}
HttpClientBuilder struct {
options []HttpClientAttributer
}
)
func (*HttpClient) init(method string, options ...HttpClientAttributer) *HttpClient {
ins := new(HttpClient)
ins.Set(Method(method))
// ins.Set(Transport(&http.Transport{}))
ins.Set(Headers(map[string][]string{}))
return ins.Set(options...)
}
func (*HttpClientBuilder) New(options ...HttpClientAttributer) *HttpClientBuilder {
return &HttpClientBuilder{options: options}
}
func (my *HttpClientBuilder) GetClient() *HttpClient {
return new(HttpClient).init(http.MethodGet, my.options...)
}
func (*HttpClient) New(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodGet, options...)
}
func (*HttpClient) NewGet(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodGet, options...)
}
func (*HttpClient) NewPost(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodPost, options...)
}
func (*HttpClient) NewPut(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodPut, options...)
}
func (*HttpClient) NewPatch(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodPatch, options...)
}
func (*HttpClient) NewDelete(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodDelete, options...)
}
func (*HttpClient) NewHead(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodHead, options...)
}
func (*HttpClient) NewOptions(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodOptions, options...)
}
func (*HttpClient) NewTrace(options ...HttpClientAttributer) *HttpClient {
return new(HttpClient).init(http.MethodTrace, options...)
}
func (my *HttpClient) set(options ...HttpClientAttributer) {
if len(options) > 0 {
for _, option := range options {
option.Register(my)
if my.err != nil {
return
}
}
}
}
func (my *HttpClient) Set(options ...HttpClientAttributer) *HttpClient {
my.lock.Lock()
defer my.lock.Unlock()
my.set(options...)
return my
}
func (my *HttpClient) GetUrl() string {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getUrl()
}
func (my *HttpClient) getUrl() string {
queries := url.Values{}
if len(my.queries) > 0 {
for k, v := range my.queries {
queries.Add(k, cast.ToString(v))
}
}
return str.BufferApp.NewString(my.url).S("?", queries.Encode()).String()
}
func (my *HttpClient) GetQueries() map[string]any {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getQueries()
}
func (my *HttpClient) getQueries() map[string]any { return my.queries }
func (my *HttpClient) GetMethod() string {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getMethod()
}
func (my *HttpClient) getMethod() string { return my.method }
func (my *HttpClient) GetHeaders() map[string][]string {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getHeaders()
}
func (my *HttpClient) getHeaders() map[string][]string { return my.headers }
func (my *HttpClient) GetBody() []byte {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getBody()
}
func (my *HttpClient) getBody() []byte { return my.requestBody }
func (my *HttpClient) GetTimeout() time.Duration {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getTimeout()
}
func (my *HttpClient) getTimeout() time.Duration { return my.timeout }
func (my *HttpClient) GetTransport() *http.Transport {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getTransport()
}
func (my *HttpClient) getTransport() *http.Transport { return my.transport }
func (my *HttpClient) GetCert() []byte {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getCert()
}
func (my *HttpClient) getCert() []byte { return my.cert }
func (my *HttpClient) GetRawRequest() *http.Request {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getRawRequest()
}
func (my *HttpClient) getRawRequest() *http.Request { return my.rawRequest }
func (my *HttpClient) GetRawResponse() *http.Response {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getRawResponse()
}
func (my *HttpClient) getRawResponse() *http.Response { return my.rawResponse }
func (my *HttpClient) GetClient() *http.Client {
my.lock.RLock()
defer my.lock.RUnlock()
return my.getClient()
}
func (my *HttpClient) getClient() *http.Client { return my.client }
func (my *HttpClient) Send() *HttpClient {
my.lock.Lock()
defer my.lock.Unlock()
if my.err != nil {
return my
}
if my.rawRequest, my.err = http.NewRequest(my.method, my.getUrl(), bytes.NewReader(my.requestBody)); my.err != nil {
return my
}
for key, values := range my.headers {
my.rawRequest.Header[key] = append(my.rawRequest.Header[key], values...)
}
if len(my.cert) > 0 {
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(my.cert) {
my.err = errors.New("生成TLS证书失败")
return my
}
my.transport.TLSClientConfig = &tls.Config{RootCAs: certPool}
}
my.client = &http.Client{}
// 发送新的请求
if my.transport != nil {
my.client.Transport = my.transport
}
// 设置超时
if my.timeout > 0 {
my.client.Timeout = my.timeout
}
if my.rawResponse, my.err = my.client.Do(my.rawRequest); my.err != nil {
return my
}
if my.autoCopy {
my.ParseBody()
my.rawResponse.Body = io.NopCloser(bytes.NewBuffer(my.responseBody)) // 还原响应体
}
return my
}
func (my *HttpClient) ParseBody() {
var (
buffer = bytes.NewBuffer([]byte{})
written int64
)
if my.err != nil {
return
}
my.responseBody = []byte{}
if my.rawResponse == nil {
return
}
// 读取新地响应的主体
if my.rawResponse.ContentLength > 1*1024*1024 { // 1MB
if written, my.err = io.Copy(buffer, my.rawResponse.Body); my.err != nil {
return
}
if written < 1 {
return
}
if buffer.Len() == 0 {
return
}
my.responseBody = buffer.Bytes()
} else {
if my.responseBody, my.err = io.ReadAll(my.rawResponse.Body); my.err != nil {
return
}
}
}
func (my *HttpClient) ToJson(target any, keys ...any) *HttpClient {
my.lock.RLock()
defer my.lock.RUnlock()
defer func() { _ = my.rawResponse.Body.Close() }()
if my.err != nil {
return my
}
if my.responseBody == nil {
my.ParseBody()
}
if len(my.responseBody) == 0 {
return my
}
return operation.TernaryFuncAll(
func() bool { return len(keys) > 0 },
func() *HttpClient {
jsonIter.Get(my.responseBody, keys...).ToVal(&target)
return my
}, func() *HttpClient {
my.err = json.Unmarshal(my.responseBody, &target)
return my
},
)
}
func (my *HttpClient) ToXml(target any) *HttpClient {
my.lock.RLock()
defer my.lock.RUnlock()
defer func() { _ = my.rawResponse.Body.Close() }()
if my.err != nil {
return my
}
if my.responseBody == nil {
my.ParseBody()
}
if len(my.responseBody) == 0 {
return my
}
my.err = xml.Unmarshal(my.responseBody, &target)
return my
}
func (my *HttpClient) ToBytes() []byte {
my.lock.RLock()
defer my.lock.RUnlock()
defer func() { _ = my.rawResponse.Body.Close() }()
if my.err != nil {
return []byte{}
}
if my.responseBody == nil {
my.ParseBody()
}
if len(my.responseBody) == 0 {
return nil
}
return my.responseBody
}
func (my *HttpClient) ToWriter(writer http.ResponseWriter) *HttpClient {
my.lock.RLock()
defer my.lock.RUnlock()
defer func() { _ = my.rawResponse.Body.Close() }()
if my.err != nil {
return my
}
_, my.err = io.Copy(writer, my.rawResponse.Body)
return my
}
func (my *HttpClient) Error() error {
var err error
defer func() { my.err = nil }()
err = my.err
return err
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jericho-yu/aid.git
git@gitee.com:jericho-yu/aid.git
jericho-yu
aid
aid
v1.35.18

搜索帮助