github.com/zly-app/zapp@v1.3.3/pkg/utils/proxy.go (about) 1 package utils 2 3 import ( 4 "context" 5 "fmt" 6 "net" 7 "net/http" 8 "net/url" 9 "strings" 10 11 "golang.org/x/net/proxy" 12 ) 13 14 type ISocks5Proxy interface { 15 Dial(network, addr string) (c net.Conn, err error) 16 DialContext(ctx context.Context, network, address string) (net.Conn, error) 17 } 18 19 type Socks5Proxy struct { 20 dial func(network, addr string) (c net.Conn, err error) 21 dialContext func(ctx context.Context, network, address string) (net.Conn, error) 22 } 23 24 func (s *Socks5Proxy) Dial(network, addr string) (c net.Conn, err error) { 25 return s.dial(network, addr) 26 } 27 28 func (s *Socks5Proxy) DialContext(ctx context.Context, network, address string) (net.Conn, error) { 29 return s.dialContext(ctx, network, address) 30 } 31 32 /* 33 创建一个socks5代理 34 35 address 代理地址. 支持socks5, socks5h. 示例: socks5://127.0.0.1:1080 socks5://user:pwd@127.0.0.1:1080 36 */ 37 func NewSocks5Proxy(address string) (ISocks5Proxy, error) { 38 // 解析地址 39 u, err := url.Parse(address) 40 if err != nil { 41 return nil, fmt.Errorf("address无法解析: %v", err) 42 } 43 44 scheme := strings.ToLower(u.Scheme) 45 switch scheme { 46 case "socks5", "socks5h": 47 var auth *proxy.Auth 48 if u.User != nil { 49 pwd, ok := u.User.Password() 50 auth = &proxy.Auth{User: u.User.Username()} 51 if ok { 52 auth.Password = pwd 53 } 54 } 55 56 dialer, err := proxy.SOCKS5("tcp", u.Host, auth, nil) 57 if err != nil { 58 return nil, fmt.Errorf("dialer生成失败: %v", err) 59 } 60 61 var dialCtx func(ctx context.Context, network, address string) (net.Conn, error) 62 if d, ok := dialer.(proxy.ContextDialer); ok { 63 dialCtx = d.DialContext 64 } else { 65 dialCtx = func(ctx context.Context, network, address string) (net.Conn, error) { 66 return dialer.Dial(network, address) 67 } 68 } 69 70 sp := &Socks5Proxy{ 71 dial: dialer.Dial, 72 dialContext: dialCtx, 73 } 74 return sp, nil 75 } 76 return nil, fmt.Errorf("address的scheme不支持: %s", scheme) 77 } 78 79 type IHttpProxy interface { 80 SetProxy(transport *http.Transport) 81 } 82 83 type HttpProxy struct { 84 p func(request *http.Request) (*url.URL, error) 85 s5 ISocks5Proxy 86 } 87 88 func (h *HttpProxy) SetProxy(transport *http.Transport) { 89 if h.s5 != nil { 90 transport.DialContext = h.s5.DialContext 91 return 92 } 93 94 transport.Proxy = h.p 95 } 96 97 /* 98 创建一个http代理 99 100 address 代理地址. 支持 http, https, socks5, socks5h. 示例: https://127.0.0.1:1080 https://user:pwd@127.0.0.1:1080 101 */ 102 func NewHttpProxy(address string) (IHttpProxy, error) { 103 // 解析地址 104 u, err := url.Parse(address) 105 if err != nil { 106 return nil, fmt.Errorf("address无法解析: %v", err) 107 } 108 109 scheme := strings.ToLower(u.Scheme) 110 switch scheme { 111 case "http", "https": 112 p := func(request *http.Request) (*url.URL, error) { 113 return u, nil 114 } 115 return &HttpProxy{p: p}, nil 116 case "socks5", "socks5h": 117 s5, err := NewSocks5Proxy(address) 118 if err != nil { 119 return nil, err 120 } 121 return &HttpProxy{s5: s5}, nil 122 } 123 return nil, fmt.Errorf("address的scheme不支持: %s", scheme) 124 }