host string
match bool
}{
- {"localhost", false}, // match completely
+ // Never proxy localhost:
+ {"localhost:80", false},
+ {"127.0.0.1", false},
+ {"127.0.0.2", false},
+ {"[::1]", false},
+ {"[::2]", true}, // not a loopback address
+
{"barbaz.net", false}, // match as .barbaz.net
- {"foobar.com:443", false}, // have a port but match
+ {"foobar.com", false}, // have a port but match
{"foofoobar.com", true}, // not match as a part of foobar.com
{"baz.com", true}, // not match as a part of barbaz.com
{"localhost.net", true}, // not match as suffix of address
func TestUseProxy(t *testing.T) {
oldenv := os.Getenv("NO_PROXY")
- no_proxy := "foobar.com, .barbaz.net , localhost"
- os.Setenv("NO_PROXY", no_proxy)
defer os.Setenv("NO_PROXY", oldenv)
+ no_proxy := "foobar.com, .barbaz.net"
+ os.Setenv("NO_PROXY", no_proxy)
+
tr := &Transport{}
for _, test := range UseProxyTests {
- if tr.useProxy(test.host) != test.match {
- if test.match {
- t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
- } else {
- t.Errorf("not expected: '%s' shouldn't match as '%s'", test.host, no_proxy)
- }
+ if tr.useProxy(test.host+":80") != test.match {
+ t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
}
}
}
import (
"bufio"
+ "bytes"
"compress/gzip"
"crypto/tls"
"encoding/base64"
// useProxy returns true if requests to addr should use a proxy,
// according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
func (t *Transport) useProxy(addr string) bool {
if len(addr) == 0 {
return true
}
+ host, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return false
+ }
+ if host == "localhost" {
+ return false
+ }
+ if ip := net.ParseIP(host); ip != nil {
+ if ip4 := ip.To4(); ip4 != nil && ip4[0] == 127 {
+ // 127.0.0.0/8 loopback isn't proxied.
+ return false
+ }
+ if bytes.Equal(ip, net.IPv6loopback) {
+ return false
+ }
+ }
+
no_proxy := t.getenvEitherCase("NO_PROXY")
if no_proxy == "*" {
return false
// Well-known IPv6 addresses
var (
- IPzero = make(IP, IPv6len) // all zeros
+ IPzero = make(IP, IPv6len) // all zeros
+ IPv6loopback = IP([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
)
// Is p all zeros?