From a8eed30db5ea3f826cd9ee3fea9809da005c6073 Mon Sep 17 00:00:00 2001 From: starainrt Date: Mon, 14 Jul 2025 18:23:14 +0800 Subject: [PATCH] add http client control --- curl.go | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/curl.go b/curl.go index b346a89..674e836 100644 --- a/curl.go +++ b/curl.go @@ -855,6 +855,14 @@ func (r *Request) AddFileWithNameAndTypeNoError(formName, filepath, filename, fi return r } +func (r *Request) HttpClient() (*http.Client, error) { + err := applyOptions(r) + if err != nil { + return nil, err + } + return r.rawClient, nil +} + type RequestFile struct { FormName string FileName string @@ -1261,8 +1269,9 @@ func (r *RequestOpts) WithAutoCalcContentLength(autoCalcContentLength bool) Requ type Response struct { *http.Response - req Request - data *Body + req Request + data *Body + rawClient *http.Client } type Body struct { @@ -1325,6 +1334,24 @@ func (r *Response) Body() *Body { return r.data } +func (r *Response) Close() error { + if r != nil && r.data != nil && r.data.raw != nil { + return r.Response.Body.Close() + } + return nil +} + +func (r *Response) CloseAll() error { + if r.rawClient != nil { + r.rawClient.CloseIdleConnections() + } + return r.Close() +} + +func (r *Response) HttpClient() *http.Client { + return r.rawClient +} + func Curl(r *Request) (*Response, error) { r.errInfo = nil err := applyOptions(r) @@ -1333,9 +1360,10 @@ func Curl(r *Request) (*Response, error) { } resp, err := r.rawClient.Do(r.rawRequest) var res = Response{ - Response: resp, - req: *r, - data: new(Body), + Response: resp, + req: *r, + data: new(Body), + rawClient: r.rawClient, } if err != nil { res.Response = &http.Response{} @@ -1376,6 +1404,17 @@ func NewRequestWithContext(ctx context.Context, uri string, method string, opts return newRequest(ctx, uri, method, opts...) } +func NewHttpClient(opts ...RequestOpt) (*http.Client, error) { + req, err := newRequest(context.Background(), "", "", opts...) + if err != nil { + return nil, err + } + defer func() { + req = nil + }() + return req.HttpClient() +} + func newRequest(ctx context.Context, uri string, method string, opts ...RequestOpt) (*Request, error) { var req *http.Request var err error @@ -1393,7 +1432,7 @@ func newRequest(ctx context.Context, uri string, method string, opts ...RequestO method: method, RequestOpts: RequestOpts{ rawRequest: req, - rawClient: new(http.Client), + rawClient: nil, timeout: DefaultTimeout, dialTimeout: DefaultDialTimeout, autoFetchRespBody: DefaultFetchRespBody, @@ -1416,10 +1455,13 @@ func newRequest(ctx context.Context, uri string, method string, opts ...RequestO } } } - if r.transport == nil { + if r.transport == nil && !r.doRawTransport { r.transport = &http.Transport{} } - if r.doRawTransport { + if r.rawClient == nil && !r.doRawClient { + r.rawClient = new(http.Client) + } + if !r.doRawTransport { if r.skipTLSVerify { if r.transport.TLSClientConfig == nil { r.transport.TLSClientConfig = &tls.Config{} @@ -1670,3 +1712,36 @@ func copyWithContext(ctx context.Context, recall func(string, int64, int64), fil } } } + +func NewReqWithClient(client *http.Client, uri string, opts ...RequestOpt) *Request { + return NewSimpleRequestWithClient(client, uri, "GET", opts...) +} + +func NewReqWithContextWithClient(ctx context.Context, client *http.Client, uri string, opts ...RequestOpt) *Request { + return NewSimpleRequestWithContextWithClient(ctx, client, uri, "GET", opts...) +} + +func NewSimpleRequestWithClient(client *http.Client, uri string, method string, opts ...RequestOpt) *Request { + r, _ := NewRequestWithContextWithClient(context.Background(), client, uri, method, opts...) + return r +} + +func NewRequestWithClient(client *http.Client, uri string, method string, opts ...RequestOpt) (*Request, error) { + return NewRequestWithContextWithClient(context.Background(), client, uri, method, opts...) +} + +func NewSimpleRequestWithContextWithClient(ctx context.Context, client *http.Client, uri string, method string, opts ...RequestOpt) *Request { + r, _ := NewRequestWithContextWithClient(ctx, client, uri, method, opts...) + return r +} + +func NewRequestWithContextWithClient(ctx context.Context, client *http.Client, uri string, method string, opts ...RequestOpt) (*Request, error) { + req, err := newRequest(context.Background(), uri, method, opts...) + if err != nil { + return nil, err + } + req.rawClient = client + req.SetDoRawClient(true) + req.SetDoRawTransport(true) + return nil, err +}