|
9 | 9 | "net/http/httputil"
|
10 | 10 | "net/url"
|
11 | 11 | "regexp"
|
| 12 | + "strings" |
12 | 13 | "time"
|
13 | 14 |
|
14 | 15 | "github.com/Clever/sphinx/common"
|
@@ -75,7 +76,27 @@ func (d *daemon) LoadConfig(newConfig config.Config) error {
|
75 | 76 | d.proxy = newConfig.Proxy
|
76 | 77 | d.healthCheck = newConfig.HealthCheck
|
77 | 78 | target, _ := url.Parse(d.proxy.Host) // already tested for invalid Host
|
78 |
| - proxy := httputil.NewSingleHostReverseProxy(target) |
| 79 | + |
| 80 | + // This is same as httputil.NewSingleHostReverseProxy with a change of adding "req.Host = targetURL.Host" https://github.com/golang/go/issues/28168 |
| 81 | + // In future version of go we can use ReverseProxy.Rewrite instead https://github.com/golang/go/commit/a55793835f16d0242be18aff4ec0bd13494175bd |
| 82 | + targetQuery := target.RawQuery |
| 83 | + director := func(req *http.Request) { |
| 84 | + req.URL.Scheme = target.Scheme |
| 85 | + req.URL.Host = target.Host |
| 86 | + req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL) |
| 87 | + req.Host = target.Host |
| 88 | + if targetQuery == "" || req.URL.RawQuery == "" { |
| 89 | + req.URL.RawQuery = targetQuery + req.URL.RawQuery |
| 90 | + } else { |
| 91 | + req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery |
| 92 | + } |
| 93 | + if _, ok := req.Header["User-Agent"]; !ok { |
| 94 | + // explicitly disable User-Agent so it's not set to default value |
| 95 | + req.Header.Set("User-Agent", "") |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + proxy := &httputil.ReverseProxy{Director: director} |
79 | 100 |
|
80 | 101 | // An attempt to fix cancelled DNS requests resulting in 502 errors
|
81 | 102 | // See https://groups.google.com/d/msg/golang-nuts/oiBBZfUb2hM/9S_JB6g2EAAJ
|
@@ -139,3 +160,36 @@ func New(config config.Config) (Daemon, error) {
|
139 | 160 | }
|
140 | 161 | return out, nil
|
141 | 162 | }
|
| 163 | + |
| 164 | +func singleJoiningSlash(a, b string) string { |
| 165 | + aslash := strings.HasSuffix(a, "/") |
| 166 | + bslash := strings.HasPrefix(b, "/") |
| 167 | + switch { |
| 168 | + case aslash && bslash: |
| 169 | + return a + b[1:] |
| 170 | + case !aslash && !bslash: |
| 171 | + return a + "/" + b |
| 172 | + } |
| 173 | + return a + b |
| 174 | +} |
| 175 | + |
| 176 | +func joinURLPath(a, b *url.URL) (path, rawpath string) { |
| 177 | + if a.RawPath == "" && b.RawPath == "" { |
| 178 | + return singleJoiningSlash(a.Path, b.Path), "" |
| 179 | + } |
| 180 | + // Same as singleJoiningSlash, but uses EscapedPath to determine |
| 181 | + // whether a slash should be added |
| 182 | + apath := a.EscapedPath() |
| 183 | + bpath := b.EscapedPath() |
| 184 | + |
| 185 | + aslash := strings.HasSuffix(apath, "/") |
| 186 | + bslash := strings.HasPrefix(bpath, "/") |
| 187 | + |
| 188 | + switch { |
| 189 | + case aslash && bslash: |
| 190 | + return a.Path + b.Path[1:], apath + bpath[1:] |
| 191 | + case !aslash && !bslash: |
| 192 | + return a.Path + "/" + b.Path, apath + "/" + bpath |
| 193 | + } |
| 194 | + return a.Path + b.Path, apath + bpath |
| 195 | +} |
0 commit comments