diff --git a/src/pkg/net/http/export_test.go b/src/pkg/net/http/export_test.go index 22b7f279689bccdb78e1aa3233ae4b366a84d50e..0494991bde6d07ecd344fcdc455b42c608a50d7c 100644 --- a/src/pkg/net/http/export_test.go +++ b/src/pkg/net/http/export_test.go @@ -63,4 +63,9 @@ func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler { return &timeoutHandler{handler, f, ""} } +func ResetCachedEnvironment() { + httpProxyEnv.reset() + noProxyEnv.reset() +} + var DefaultUserAgent = defaultUserAgent diff --git a/src/pkg/net/http/transport.go b/src/pkg/net/http/transport.go index f6871afacd7a3c26efc3d76350b314be29897da1..8fc7329e361f0915fbe966c59bf4e831ea493804 100644 --- a/src/pkg/net/http/transport.go +++ b/src/pkg/net/http/transport.go @@ -99,7 +99,7 @@ type Transport struct { // A nil URL and nil error are returned if no proxy is defined in the // environment, or a proxy should not be used for the given request. func ProxyFromEnvironment(req *Request) (*url.URL, error) { - proxy := getenvEitherCase("HTTP_PROXY") + proxy := httpProxyEnv.Get() if proxy == "" { return nil, nil } @@ -243,11 +243,42 @@ func (t *Transport) CancelRequest(req *Request) { // Private implementation past this point. // -func getenvEitherCase(k string) string { - if v := os.Getenv(strings.ToUpper(k)); v != "" { - return v +var ( + httpProxyEnv = &envOnce{ + names: []string{"HTTP_PROXY", "http_proxy"}, } - return os.Getenv(strings.ToLower(k)) + noProxyEnv = &envOnce{ + names: []string{"NO_PROXY", "no_proxy"}, + } +) + +// envOnce looks up an environment variable (optionally by multiple +// names) once. It mitigates expensive lookups on some platforms +// (e.g. Windows). +type envOnce struct { + names []string + once sync.Once + val string +} + +func (e *envOnce) Get() string { + e.once.Do(e.init) + return e.val +} + +func (e *envOnce) init() { + for _, n := range e.names { + e.val = os.Getenv(n) + if e.val != "" { + return + } + } +} + +// reset is used by tests +func (e *envOnce) reset() { + e.once = sync.Once{} + e.val = "" } func (t *Transport) connectMethodForRequest(treq *transportRequest) (*connectMethod, error) { @@ -550,7 +581,7 @@ func useProxy(addr string) bool { } } - no_proxy := getenvEitherCase("NO_PROXY") + no_proxy := noProxyEnv.Get() if no_proxy == "*" { return false } diff --git a/src/pkg/net/http/transport_test.go b/src/pkg/net/http/transport_test.go index 2ce2b6b5180c86c6c73d047e8cda3f7665b2cc19..cb54a7b419725bc546bbe8c401b6b86bd7e6e55f 100644 --- a/src/pkg/net/http/transport_test.go +++ b/src/pkg/net/http/transport_test.go @@ -1566,6 +1566,7 @@ func TestProxyFromEnvironment(t *testing.T) { for _, tt := range proxyFromEnvTests { os.Setenv("HTTP_PROXY", tt.env) os.Setenv("NO_PROXY", tt.noenv) + ResetCachedEnvironment() reqURL := tt.req if reqURL == "" { reqURL = "http://example.com"