56 lines
1.3 KiB
Go
56 lines
1.3 KiB
Go
package proxy
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"golang.org/x/net/proxy"
|
|
)
|
|
|
|
func GetTransport(proxy string) (http.RoundTripper, error) {
|
|
if proxy == "" {
|
|
return http.DefaultTransport, nil
|
|
}
|
|
proxyUrl, err := url.Parse(proxy)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse proxyUrl, url:%s, err: %w", proxy, err)
|
|
}
|
|
if proxyUrl.Host == "unix" && proxyUrl.Scheme == "socks5" &&
|
|
len(proxyUrl.Path) > 1 /* Path cannot be empty or just / */ {
|
|
return unixSocks5Proxy(proxyUrl.Path)
|
|
}
|
|
return proxyHttp(proxyUrl)
|
|
}
|
|
|
|
func unixSocks5Proxy(path string) (http.RoundTripper, error) {
|
|
// TODO: Auth?
|
|
dialer, err := proxy.SOCKS5("unix", path, nil /*auth*/, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to make socks proxy, path: %s, err: %w", path, err)
|
|
}
|
|
ctxDialer, ok := dialer.(proxy.ContextDialer)
|
|
if !ok {
|
|
panic("proxy.SOCKS5 did not return a ContextDialer")
|
|
}
|
|
trans := defaultTransport()
|
|
trans.DialContext = ctxDialer.DialContext
|
|
trans.Proxy = nil
|
|
return trans, nil
|
|
}
|
|
|
|
func proxyHttp(proxyUrl *url.URL) (http.RoundTripper, error) {
|
|
trans := defaultTransport()
|
|
trans.Proxy = http.ProxyURL(proxyUrl)
|
|
return trans, nil
|
|
}
|
|
|
|
func defaultTransport() *http.Transport {
|
|
transPtr, ok := http.DefaultTransport.(*http.Transport)
|
|
if !ok {
|
|
panic("http.DefaultTransport is not a *http.Transport")
|
|
}
|
|
trans := transPtr.Clone()
|
|
return trans
|
|
}
|