I'm trying to proxy a server using httputil.ReverseProxy but am seeing abysmal performance (about 1/10th the speed) and even worse, transfers seem to abort before they complete.
For example, via the proxy:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
99 12.7M 99 12.7M 0 0 353k 0 0:00:37 0:00:36 0:00:01 0
curl: (18) transfer closed with 14407 bytes remaining to read
And via a direct connection:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 12.7M 100 12.7M 0 0 4079k 0 0:00:03 0:00:03 --:--:-- 4559k
The code I'm using to build the ReverseProxy looks like this:
// reverseProxy adds a reverse proxy handler rooted at path which proxies all requests through target.
func reverseProxy(path string, target *url.URL) {
targetQuery := target.RawQuery
director := func(req *http.Request) {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
fmt.Println(req.URL)
}
http.Handle(path, http.StripPrefix(path, &httputil.ReverseProxy{Director: director, FlushInterval: 100 * time.Millisecond}))
}
func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
switch {
case aslash && bslash:
return a + b[1:]
case !aslash && !bslash:
return a + "/" + b
}
return a + b
}
Most of it is copied from httputil.NewSingleHostReverseProxy. I've tried various values of FlushInterval but they don't seem to improve the situation.
Any ideas as to what the problem might be?