71

I'm trying to setup the HTTP client so that it uses a proxy, however I cannot quite understand how to do it. The documentation has multiple reference to "proxy" but none of the functions seem to allow to define the proxy. What I need is something like this:

client := &http.Client{}
client.SetProxy("someip:someport") // pseudo code
resp, err := client.Get("http://example.com") // do request through proxy

Any idea how to do this in Go?

laurent
  • 88,262
  • 77
  • 290
  • 428

6 Answers6

154

lukad is correct, you could set the HTTP_PROXY environment variable, if you do this Go will use it by default.

Bash:

export HTTP_PROXY="http://proxyIp:proxyPort"

Go:

os.Setenv("HTTP_PROXY", "http://proxyIp:proxyPort")

You could also construct your own http.Client that MUST use a proxy regardless of the environment's configuration:

proxyUrl, err := url.Parse("http://proxyIp:proxyPort")
myClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}

This is useful if you can not depend on the environment's configuration, or do not want to modify it.

You could also modify the default transport used by the "net/http" package. This would affect your entire program (including the default HTTP client).

proxyUrl, err := url.Parse("http://proxyIp:proxyPort")
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(proxyUrl)}
phact
  • 7,305
  • 23
  • 27
voidlogic
  • 6,398
  • 2
  • 23
  • 21
  • In fact, I need to concurrently send several requests, each using a different proxy, so your second solution is probably what I need. However, it doesn't seem to be working, I'm getting this error for all the proxies: `Get http://stackoverflow.com: http: error connecting to proxy 87.236.233.92:8080: GetServByName: The requested name is valid, but no data of the requested type was found.` Any idea what it means? – laurent Feb 03 '13 at 05:36
  • 1
    I got my answer to this question there - http://stackoverflow.com/q/14669958/561309 – laurent Feb 03 '13 at 13:24
  • @voidlogic setting the env variable didn't work for me. I have to pass it to the http.Transport – PMat Mar 27 '18 at 23:48
  • Would this also be possible with a socks5 proxy? – C4d Sep 19 '18 at 11:12
  • If your proxy requires an username and password along with IP, the `export HTTP_PROXY="http://proxyIp:proxyPort"` becomes `export HTTP_PROXY="http://PROXY_LOGIN:PROXY_PASS@proxyIp:proxyPort"` – karthikeyan Jan 18 '23 at 10:30
16

Go will use the the proxy defined in the environment variable HTTP_PROXY if it's set. Otherwise it will use no proxy.

You could do it like this:

os.Setenv("HTTP_PROXY", "http://someip:someport")
resp, err := http.Get("http://example.com")
if err != nil {
    panic(err)
}
lukad
  • 17,287
  • 3
  • 36
  • 53
7

May you could also try this:

url_i := url.URL{}
url_proxy, _ := url_i.Parse(proxy_addr)

transport := http.Transport{}    
transport.Proxy = http.ProxyURL(url_proxy)// set proxy 
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //set ssl

client := &http.Client{}
client.Transport = transport
resp, err := client.Get("http://example.com") // do request through proxy
pi.
  • 21,112
  • 8
  • 38
  • 59
HeyJoy
  • 193
  • 2
  • 8
2

The Go built-in proxy use is briefly documented in the DefaultTransport:

// DefaultTransport .... It uses HTTP proxies
// as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and
// $no_proxy) environment variables.
var DefaultTransport RoundTripper = &Transport{
    Proxy: ProxyFromEnvironment,

This points to the usefulness of creating custom Transports from DefaultTransport vs. from scratch to take advantage of the built-in ProxyFromEnvironment function

SVUser
  • 367
  • 3
  • 9
1

If you run something like this:

HTTP_PROXY=89.x.y.z path_to_program

Then the HTTP_PROXY setting is set for that command only, which is useful if you don't want to set it for the whole shell session. Note: there's no ; between the setting and the path; if you put a semicolon, it would set (but not export) HTTP_PROXY for that shell

Graham Nicholls
  • 513
  • 1
  • 9
  • 20
0

For an alternative way, you can also use GoRequest which has a feature that you can set proxy easily for any single request.

request := gorequest.New()
resp, body, errs:= request.Proxy("http://proxy:999").Get("http://example.com").End()
resp2, body2, errs2 := request.Proxy("http://proxy2:999").Get("http://example2.com").End()

Or you can set for the whole at once.

request := gorequest.New().Proxy("http://proxy:999")
resp, body, errs:= request.Get("http://example.com").End()
resp2, body2, errs2 := request.Get("http://example2.com").End()
A-letubby
  • 8,474
  • 8
  • 38
  • 48