Skip to content

Instantly share code, notes, and snippets.

@ometa
Created February 25, 2020 16:05
Show Gist options
  • Save ometa/71d23ed48c03c003f6e4910648612859 to your computer and use it in GitHub Desktop.
Save ometa/71d23ed48c03c003f6e4910648612859 to your computer and use it in GitHub Desktop.
Golang HTTP Client using SOCKS5 proxy and DialContext
// Golang example that creates an http client that leverages a SOCKS5 proxy and a DialContext
func NewClientFromEnv() (*http.Client, error) {
proxyHost := os.Getenv("PROXY_HOST")
baseDialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
var dialContext DialContext
if proxyHost != "" {
dialSocksProxy, err := proxy.SOCKS5("tcp", proxyHost, nil, baseDialer)
if err != nil {
return nil, errors.Wrap(err, "Error creating SOCKS5 proxy")
}
if contextDialer, ok := dialSocksProxy.(proxy.ContextDialer); ok {
dialContext = contextDialer.DialContext
} else {
return nil, errors.New("Failed type assertion to DialContext")
}
logger.Debug("Using SOCKS5 proxy for http client",
zap.String("host", proxyHost),
)
} else {
dialContext = (baseDialer).DialContext
}
httpClient = newClient(dialContext)
return httpClient, nil
}
func newClient(dialContext DialContext) *http.Client {
return &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dialContext,
MaxIdleConns: 10,
IdleConnTimeout: 60 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
},
}
}
@suntong
Copy link

suntong commented Jul 7, 2021

in this example, to make it clearer, I'd not use os.Getenv("PROXY_HOST") and not http.ProxyFromEnvironment!

How to use it then? I can't see how I can pass my SOCKS5 proxy setting to the code.

Would you give another complete demo code to use it please?

resp, err := http.Get("http://example.com/") 
if err != nil { // handle error } 

defer resp.Body.Close() 
body, err := ioutil.ReadAll(resp.Body)

@zendesk-thittesdorf
Copy link

in this example, to make it clearer, I'd not use os.Getenv("PROXY_HOST") and not http.ProxyFromEnvironment!

How to use it then? I can't see how I can pass my SOCKS5 proxy setting to the code.

Would you give another complete demo code to use it please?

resp, err := http.Get("http://example.com/") 
if err != nil { // handle error } 

defer resp.Body.Close() 
body, err := ioutil.ReadAll(resp.Body)
client := NewClientFromEnv()
resp, err := client.Get("http://example.com")

@suntong
Copy link

suntong commented Aug 13, 2021

client := NewClientFromEnv()
resp, err := client.Get("http://example.com")

Thanks, and where can I find the definition of such NewClientFromEnv() please?

@volvinbur1
Copy link

volvinbur1 commented Nov 29, 2021

Thanks, and where can I find the definition of such NewClientFromEnv() please?

@suntong, Here it is. It is a part of snippet

@makew0rld
Copy link

Another way to get the dial context:

    dialer, err := proxy.SOCKS5("tcp", proxyUrl, nil, proxy.Direct)
    dialContext := func(ctx context.Context, network, address string) (net.Conn, error) {
        return dialer.Dial(network, address)
    }

Source: https://stackoverflow.com/a/63661992

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment