DEV Community

Pavel Kutáč
Pavel Kutáč

Posted on

Ignoring HTTP_PROXY environment vars in Go

Standard HTTP library in Go reads the environment variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY. But in some situations, those variables are ignored. On the other hand, the developer may want to disable the reading of those variables.


🇨🇿 V češtině si lze článek přečíst na kutac.cz

A proxy might be useful to go over the firewall of a company network when access to some sites is blocked. But a proxy is often used to debug and inspect communication during development. For example tools like HTTP Toolkit creates a local proxy server.

Every program in Go using net/http will read HTTP(S)_PROXY and NO_PROXY variables and acts accordingly. But what if the developer wants to be sure, users cannot use proxy at all? The code below is an example for explaining further issues.

func main() {
    fmt.Println(os.Getenv("HTTP_PROXY"))
    client := &http.Client{}
    resp, err := client.Get("http://localhost:8090/vm/1")
    if err != nil {
        log.Fatal(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(body))
}
Enter fullscreen mode Exit fullscreen mode

I set HTTP_PROXY and it is ignored

In the code above the content of HTTP_PROXY is printed out and then called GET request. But even if the value is set correctly, it is ignored. The main reason is the request is made to localhost which is ignored as well as 127.x.x.x. Luckily it is easy to go around this.

It is enough to set custom domain in /etc/hosts on Linux or C:\Windows\System32\drivers\etc\hosts on Windows by adding 127.0.0.1 localserver.loc and then change the code above.

resp, err := client.Get("http://localserver.loc:8090/vm/1")
Enter fullscreen mode Exit fullscreen mode

This is documented behavior, but quite deeply. You can find it in source opensource.google/x/net/http/httpproxy/proxy.go line 118 and on line 181 is exact if which is responsible for that.

How to disable reading PROXY environment variables

You can use variable NO_PROXY to set which URLs will never go through a proxy. You can specify all with NO_PROXY=* or list URLs delimited by comma. But what to do if you as a developer wants to ignore all those variables? Then the own Transport of HTTP Client must be set.

transport := http.DefaultTransport
transport.(*http.Transport).Proxy = nil
client := &http.Client{
    Transport: transport,
}
Enter fullscreen mode Exit fullscreen mode

Discussion (0)