gf/net/gclient/gclient_config.go

200 lines
5.1 KiB
Go

// 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 gclient
import (
"context"
"crypto/tls"
"net"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
"time"
"golang.org/x/net/proxy"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
// SetBrowserMode enables browser mode of the client.
// When browser mode is enabled, it automatically saves and sends cookie content
// from and to server.
func (c *Client) SetBrowserMode(enabled bool) *Client {
if enabled {
jar, _ := cookiejar.New(nil)
c.Jar = jar
}
return c
}
// SetHeader sets a custom HTTP header pair for the client.
func (c *Client) SetHeader(key, value string) *Client {
c.header[key] = value
return c
}
// SetHeaderMap sets custom HTTP headers with map.
func (c *Client) SetHeaderMap(m map[string]string) *Client {
for k, v := range m {
c.header[k] = v
}
return c
}
// SetAgent sets the User-Agent header for client.
func (c *Client) SetAgent(agent string) *Client {
c.header[httpHeaderUserAgent] = agent
return c
}
// SetContentType sets HTTP content type for the client.
func (c *Client) SetContentType(contentType string) *Client {
c.header[httpHeaderContentType] = contentType
return c
}
// SetHeaderRaw sets custom HTTP header using raw string.
func (c *Client) SetHeaderRaw(headers string) *Client {
for _, line := range gstr.SplitAndTrim(headers, "\n") {
array, _ := gregex.MatchString(httpRegexHeaderRaw, line)
if len(array) >= 3 {
c.header[array[1]] = array[2]
}
}
return c
}
// SetCookie sets a cookie pair for the client.
func (c *Client) SetCookie(key, value string) *Client {
c.cookies[key] = value
return c
}
// SetCookieMap sets cookie items with map.
func (c *Client) SetCookieMap(m map[string]string) *Client {
for k, v := range m {
c.cookies[k] = v
}
return c
}
// SetPrefix sets the request server URL prefix.
func (c *Client) SetPrefix(prefix string) *Client {
c.prefix = prefix
return c
}
// SetTimeout sets the request timeout for the client.
func (c *Client) SetTimeout(t time.Duration) *Client {
c.Client.Timeout = t
return c
}
// SetBasicAuth sets HTTP basic authentication information for the client.
func (c *Client) SetBasicAuth(user, pass string) *Client {
c.authUser = user
c.authPass = pass
return c
}
// SetRetry sets retry count and interval.
func (c *Client) SetRetry(retryCount int, retryInterval time.Duration) *Client {
c.retryCount = retryCount
c.retryInterval = retryInterval
return c
}
// SetRedirectLimit limits the number of jumps.
func (c *Client) SetRedirectLimit(redirectLimit int) *Client {
c.CheckRedirect = func(req *http.Request, via []*http.Request) error {
if len(via) >= redirectLimit {
return http.ErrUseLastResponse
}
return nil
}
return c
}
// SetProxy set proxy for the client.
// This func will do nothing when the parameter `proxyURL` is empty or in wrong pattern.
// 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) SetProxy(proxyURL string) {
if strings.TrimSpace(proxyURL) == "" {
return
}
_proxy, err := url.Parse(proxyURL)
if err != nil {
intlog.Errorf(context.TODO(), `%+v`, err)
return
}
if _proxy.Scheme == httpProtocolName {
if v, ok := c.Transport.(*http.Transport); ok {
v.Proxy = http.ProxyURL(_proxy)
}
} else {
auth := &proxy.Auth{}
user := _proxy.User.Username()
if user != "" {
auth.User = user
password, hasPassword := _proxy.User.Password()
if hasPassword && password != "" {
auth.Password = password
}
} else {
auth = nil
}
// refer to the source code, error is always nil
dialer, err := proxy.SOCKS5(
"tcp",
_proxy.Host,
auth,
&net.Dialer{
Timeout: c.Client.Timeout,
KeepAlive: c.Client.Timeout,
},
)
if err != nil {
intlog.Errorf(context.TODO(), `%+v`, err)
return
}
if v, ok := c.Transport.(*http.Transport); ok {
v.DialContext = func(ctx context.Context, network, addr string) (conn net.Conn, e error) {
return dialer.Dial(network, addr)
}
}
// c.SetTimeout(10*time.Second)
}
}
// SetTLSKeyCrt sets the certificate and key file for TLS configuration of client.
func (c *Client) SetTLSKeyCrt(crtFile, keyFile string) error {
tlsConfig, err := LoadKeyCrt(crtFile, keyFile)
if err != nil {
return gerror.Wrap(err, "LoadKeyCrt failed")
}
if v, ok := c.Transport.(*http.Transport); ok {
tlsConfig.InsecureSkipVerify = true
v.TLSClientConfig = tlsConfig
return nil
}
return gerror.New(`cannot set TLSClientConfig for custom Transport of the client`)
}
// SetTLSConfig sets the TLS configuration of client.
func (c *Client) SetTLSConfig(tlsConfig *tls.Config) error {
if v, ok := c.Transport.(*http.Transport); ok {
v.TLSClientConfig = tlsConfig
return nil
}
return gerror.New(`cannot set TLSClientConfig for custom Transport of the client`)
}