1
0
mirror of https://github.com/golang/go synced 2024-11-23 22:30:05 -07:00

net/http: cache transport environment lookup

Apparently this is expensive on Windows.

Fixes #7020

R=golang-codereviews, alex.brainman, mattn.jp, dvyukov
CC=golang-codereviews
https://golang.org/cl/52840043
This commit is contained in:
Brad Fitzpatrick 2014-01-16 10:25:45 -08:00
parent fc908a0298
commit 4deead7645
3 changed files with 43 additions and 6 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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"