Skip to content

Commit 82ae643

Browse files
committed
net/http: match curl and others' NO_PROXY wildcard handling
NO_PROXY="example.com" should match "foo.example.com", just the same as NO_PROXY=".example.com". This is what curl and Python do. Fixes #4574 R=golang-dev, rsc CC=golang-dev https://golang.org/cl/7005049
1 parent 403f012 commit 82ae643

File tree

3 files changed

+55
-17
lines changed

3 files changed

+55
-17
lines changed

src/pkg/net/http/proxy_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var UseProxyTests = []struct {
3131
{"localhost.net", true}, // not match as suffix of address
3232
{"local.localhost", true}, // not match as prefix as address
3333
{"barbarbaz.net", true}, // not match because NO_PROXY have a '.'
34-
{"www.foobar.com", true}, // not match because NO_PROXY is not .foobar.com
34+
{"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com"
3535
}
3636

3737
func TestUseProxy(t *testing.T) {

src/pkg/net/http/transport.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,15 @@ func useProxy(addr string) bool {
450450
if hasPort(p) {
451451
p = p[:strings.LastIndex(p, ":")]
452452
}
453-
if addr == p || (p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:])) {
453+
if addr == p {
454+
return false
455+
}
456+
if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) {
457+
// no_proxy ".foo.com" matches "bar.foo.com" or "foo.com"
458+
return false
459+
}
460+
if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' {
461+
// no_proxy "foo.com" matches "bar.foo.com"
454462
return false
455463
}
456464
}

src/pkg/net/http/transport_test.go

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,35 +1115,65 @@ func TestTransportNoHost(t *testing.T) {
11151115
}
11161116
}
11171117

1118-
var proxyFromEnvTests = []struct {
1118+
type proxyFromEnvTest struct {
1119+
req string // URL to fetch; blank means "http://example.com"
11191120
env string
1120-
wanturl string
1121+
noenv string
1122+
want string
11211123
wanterr error
1122-
}{
1123-
{"127.0.0.1:8080", "http://127.0.0.1:8080", nil},
1124-
{"cache.corp.example.com:1234", "http://cache.corp.example.com:1234", nil},
1125-
{"cache.corp.example.com", "http://cache.corp.example.com", nil},
1126-
{"https://cache.corp.example.com", "https://cache.corp.example.com", nil},
1127-
{"http://127.0.0.1:8080", "http://127.0.0.1:8080", nil},
1128-
{"https://127.0.0.1:8080", "https://127.0.0.1:8080", nil},
1129-
{"", "<nil>", nil},
1124+
}
1125+
1126+
func (t proxyFromEnvTest) String() string {
1127+
var buf bytes.Buffer
1128+
if t.env != "" {
1129+
fmt.Fprintf(&buf, "http_proxy=%q", t.env)
1130+
}
1131+
if t.noenv != "" {
1132+
fmt.Fprintf(&buf, " no_proxy=%q", t.noenv)
1133+
}
1134+
req := "http://example.com"
1135+
if t.req != "" {
1136+
req = t.req
1137+
}
1138+
fmt.Fprintf(&buf, " req=%q", req)
1139+
return strings.TrimSpace(buf.String())
1140+
}
1141+
1142+
var proxyFromEnvTests = []proxyFromEnvTest{
1143+
{env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"},
1144+
{env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"},
1145+
{env: "cache.corp.example.com", want: "http://cache.corp.example.com"},
1146+
{env: "https://cache.corp.example.com", want: "https://cache.corp.example.com"},
1147+
{env: "http://127.0.0.1:8080", want: "http://127.0.0.1:8080"},
1148+
{env: "https://127.0.0.1:8080", want: "https://127.0.0.1:8080"},
1149+
{want: "<nil>"},
1150+
{noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
1151+
{noenv: ".example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
1152+
{noenv: "ample.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
1153+
{noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"},
1154+
{noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
11301155
}
11311156

11321157
func TestProxyFromEnvironment(t *testing.T) {
11331158
os.Setenv("HTTP_PROXY", "")
11341159
os.Setenv("http_proxy", "")
11351160
os.Setenv("NO_PROXY", "")
11361161
os.Setenv("no_proxy", "")
1137-
for i, tt := range proxyFromEnvTests {
1162+
for _, tt := range proxyFromEnvTests {
11381163
os.Setenv("HTTP_PROXY", tt.env)
1139-
req, _ := NewRequest("GET", "http://example.com", nil)
1164+
os.Setenv("NO_PROXY", tt.noenv)
1165+
reqURL := tt.req
1166+
if reqURL == "" {
1167+
reqURL = "http://example.com"
1168+
}
1169+
req, _ := NewRequest("GET", reqURL, nil)
11401170
url, err := ProxyFromEnvironment(req)
11411171
if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
1142-
t.Errorf("%d. got error = %q, want %q", i, g, e)
1172+
t.Errorf("%v: got error = %q, want %q", tt, g, e)
11431173
continue
11441174
}
1145-
if got := fmt.Sprintf("%s", url); got != tt.wanturl {
1146-
t.Errorf("%d. got URL = %q, want %q", i, url, tt.wanturl)
1175+
if got := fmt.Sprintf("%s", url); got != tt.want {
1176+
t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
11471177
}
11481178
}
11491179
}

0 commit comments

Comments
 (0)