add a SetProxy function and a chaining function Proxy for ghttp.Client to do HTTP request via proxy. #285

This commit is contained in:
linx
2020-06-22 21:12:11 +08:00
committed by kirileec
parent c04be14cd9
commit bcc9153991
3 changed files with 77 additions and 0 deletions

1
go.mod
View File

@ -15,6 +15,7 @@ require (
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/olekukonko/tablewriter v0.0.1
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
golang.org/x/net v0.0.0-20200602114024-627f9648deb9
golang.org/x/text v0.3.2
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
)

View File

@ -135,3 +135,17 @@ func (c *Client) Retry(retryCount int, retryInterval time.Duration) *Client {
newClient.SetRetry(retryCount, retryInterval)
return c
}
// Proxy is a chaining function,
// which sets proxy for next request.
// Make sure you pass the correct `proxyURL`.
// 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.SetProxy(proxyURL)
return c
}

View File

@ -10,7 +10,11 @@ import (
"context"
"crypto/tls"
"github.com/gogf/gf/text/gstr"
"golang.org/x/net/proxy"
"net"
"net/http"
"net/url"
"strings"
"time"
"github.com/gogf/gf/text/gregex"
@ -158,3 +162,61 @@ func (c *Client) SetRedirectLimit(redirectLimit int) *Client {
}
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 {
return
}
if _proxy.Scheme == "http" {
c.Transport = &http.Transport{
Proxy: http.ProxyURL(_proxy),
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
DisableKeepAlives: true,
}
} else {
var 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: 30 * time.Second,
KeepAlive: 30 * time.Second,
},
)
if err != nil {
return
}
c.Transport = &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, e error) {
return dialer.Dial(network, addr)
},
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
DisableKeepAlives: true,
}
}
}