diff --git a/frame/gins/gins_httpclient.go b/frame/gins/gins_httpclient.go new file mode 100644 index 000000000..8bf8f579c --- /dev/null +++ b/frame/gins/gins_httpclient.go @@ -0,0 +1,27 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gins + +import ( + "fmt" + + "github.com/gogf/gf/v2/net/ghttp" +) + +const ( + frameCoreComponentNameHttpClient = "gf.core.component.httpclient" +) + +// HttpClient returns an instance of http client with specified name. +func HttpClient(name ...interface{}) *ghttp.Client { + var ( + instanceKey = fmt.Sprintf("%s.%v", frameCoreComponentNameHttpClient, name) + ) + return localInstances.GetOrSetFuncLock(instanceKey, func() interface{} { + return ghttp.NewClient() + }).(*ghttp.Client) +} diff --git a/frame/gins/gins_z_unit_httpclient_test.go b/frame/gins/gins_z_unit_httpclient_test.go new file mode 100644 index 000000000..b250ae7b5 --- /dev/null +++ b/frame/gins/gins_z_unit_httpclient_test.go @@ -0,0 +1,30 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gins_test + +import ( + "fmt" + "testing" + + "github.com/gogf/gf/v2/frame/gins" + "github.com/gogf/gf/v2/test/gtest" +) + +func Test_Client(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + c = gins.HttpClient() + c1 = gins.HttpClient("c1") + c2 = gins.HttpClient("c2") + ) + c.SetAgent("test1") + c.SetAgent("test2") + t.AssertNE(fmt.Sprintf(`%p`, c), fmt.Sprintf(`%p`, c1)) + t.AssertNE(fmt.Sprintf(`%p`, c), fmt.Sprintf(`%p`, c2)) + t.AssertNE(fmt.Sprintf(`%p`, c1), fmt.Sprintf(`%p`, c2)) + }) +} diff --git a/net/ghttp/internal/client/client.go b/net/ghttp/internal/client/client.go index 1738495db..4802c6946 100644 --- a/net/ghttp/internal/client/client.go +++ b/net/ghttp/internal/client/client.go @@ -32,7 +32,6 @@ import ( type Client struct { http.Client // Underlying HTTP Client. dump bool // Mark this request will be dumped. - parent *Client // Parent http client, this is used for chaining operations. header map[string]string // Custom header map. cookies map[string]string // Custom cookie map. prefix string // Prefix for request. diff --git a/net/ghttp/internal/client/client_chain.go b/net/ghttp/internal/client/client_chain.go index 7069db7f8..898360987 100644 --- a/net/ghttp/internal/client/client_chain.go +++ b/net/ghttp/internal/client/client_chain.go @@ -13,10 +13,7 @@ import ( // Prefix is a chaining function, // which sets the URL prefix for next request of this client. func (c *Client) Prefix(prefix string) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetPrefix(prefix) return newClient } @@ -24,10 +21,7 @@ func (c *Client) Prefix(prefix string) *Client { // Header is a chaining function, // which sets custom HTTP headers with map for next request. func (c *Client) Header(m map[string]string) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetHeaderMap(m) return newClient } @@ -35,10 +29,7 @@ func (c *Client) Header(m map[string]string) *Client { // HeaderRaw is a chaining function, // which sets custom HTTP header using raw string for next request. func (c *Client) HeaderRaw(headers string) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetHeaderRaw(headers) return newClient } @@ -46,10 +37,7 @@ func (c *Client) HeaderRaw(headers string) *Client { // Cookie is a chaining function, // which sets cookie items with map for next request. func (c *Client) Cookie(m map[string]string) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetCookieMap(m) return newClient } @@ -57,10 +45,7 @@ func (c *Client) Cookie(m map[string]string) *Client { // ContentType is a chaining function, // which sets HTTP content type for the next request. func (c *Client) ContentType(contentType string) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetContentType(contentType) return newClient } @@ -70,10 +55,7 @@ func (c *Client) ContentType(contentType string) *Client { // // Note that it also checks and encodes the parameter to JSON format automatically. func (c *Client) ContentJson() *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetContentType("application/json") return newClient } @@ -83,10 +65,7 @@ func (c *Client) ContentJson() *Client { // // Note that it also checks and encodes the parameter to XML format automatically. func (c *Client) ContentXml() *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetContentType("application/xml") return newClient } @@ -94,10 +73,7 @@ func (c *Client) ContentXml() *Client { // Timeout is a chaining function, // which sets the timeout for next request. func (c *Client) Timeout(t time.Duration) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetTimeout(t) return newClient } @@ -105,10 +81,7 @@ func (c *Client) Timeout(t time.Duration) *Client { // BasicAuth is a chaining function, // which sets HTTP basic authentication information for next request. func (c *Client) BasicAuth(user, pass string) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetBasicAuth(user, pass) return newClient } @@ -116,10 +89,7 @@ func (c *Client) BasicAuth(user, pass string) *Client { // Retry is a chaining function, // which sets retry count and interval when failure for next request. func (c *Client) Retry(retryCount int, retryInterval time.Duration) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetRetry(retryCount, retryInterval) return newClient } @@ -127,10 +97,7 @@ func (c *Client) Retry(retryCount int, retryInterval time.Duration) *Client { // Dump is a chaining function, // which enables/disables dump feature for this request. func (c *Client) Dump(dump ...bool) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() if len(dump) > 0 { newClient.SetDump(dump[0]) } else { @@ -145,10 +112,7 @@ func (c *Client) Dump(dump ...bool) *Client { // The correct pattern is like `http://USER:PASSWORD@IP:PORT` or `socks5://USER:PASSWORD@IP:PORT`. // Only `http` and `socks5` proxies are supported currently. func (c *Client) Proxy(proxyURL string) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetProxy(proxyURL) return newClient } @@ -156,10 +120,7 @@ func (c *Client) Proxy(proxyURL string) *Client { // RedirectLimit is a chaining function, // which sets the redirect limit the number of jumps for the request. func (c *Client) RedirectLimit(redirectLimit int) *Client { - newClient := c - if c.parent == nil { - newClient = c.Clone() - } + newClient := c.Clone() newClient.SetRedirectLimit(redirectLimit) return newClient }