net/tshttpproxy: add GetProxyForURL negative cache

Otherwise when PAC server is down, we log, and each log entry is a new
HTTP request (from logtail) and a new GetProxyForURL call, which again
logs, non-stop. This is also nicer to the WinHTTP service.

Then also hook up link change notifications to the cache to reset it
if there's a chance the network might work sooner.
This commit is contained in:
Brad Fitzpatrick
2020-09-21 14:02:58 -07:00
parent 4cc0ed67f9
commit 5bcac4eaac
4 changed files with 46 additions and 3 deletions

View File

@@ -10,14 +10,43 @@ import (
"net/http"
"net/url"
"os"
"sync"
"time"
)
// InvalidateCache invalidates the package-level cache for ProxyFromEnvironment.
//
// It's intended to be called on network link/routing table changes.
func InvalidateCache() {
mu.Lock()
defer mu.Unlock()
noProxyUntil = time.Time{}
}
var (
mu sync.Mutex
noProxyUntil time.Time // if non-zero, time at which ProxyFromEnvironment should check again
)
func setNoProxyUntil(d time.Duration) {
mu.Lock()
defer mu.Unlock()
noProxyUntil = time.Now().Add(d)
}
// sysProxyFromEnv, if non-nil, specifies a platform-specific ProxyFromEnvironment
// func to use if http.ProxyFromEnvironment doesn't return a proxy.
// For example, WPAD PAC files on Windows.
var sysProxyFromEnv func(*http.Request) (*url.URL, error)
func ProxyFromEnvironment(req *http.Request) (*url.URL, error) {
mu.Lock()
noProxyTime := noProxyUntil
mu.Unlock()
if time.Now().Before(noProxyTime) {
return nil, nil
}
u, err := http.ProxyFromEnvironment(req)
if u != nil && err == nil {
return u, nil