diff --git a/caddyhttp/proxy/proxy.go b/caddyhttp/proxy/proxy.go index c4cd19606..68810c05b 100644 --- a/caddyhttp/proxy/proxy.go +++ b/caddyhttp/proxy/proxy.go @@ -30,6 +30,8 @@ type Upstream interface { Select() *UpstreamHost // Checks if subpath is not an ignored path AllowedPath(string) bool + // Is Upstream in transparent mode? + Transparent() bool } // UpstreamHostDownFunc can be used to customize how Down behaves. @@ -94,6 +96,7 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { start := time.Now() for time.Now().Sub(start) < tryDuration { host := upstream.Select() + if host == nil { return http.StatusBadGateway, errUnreachable } @@ -125,6 +128,9 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { if v, ok := host.UpstreamHeaders["Host"]; ok { outreq.Host = replacer.Replace(v[len(v)-1]) } + if upstream.Transparent() { + host.UpstreamHeaders.Set("Host", host.Name) + } // modify headers for request that will be sent to the upstream host upHeaders := createHeadersByRules(host.UpstreamHeaders, r.Header, replacer) for k, v := range upHeaders { diff --git a/caddyhttp/proxy/proxy_test.go b/caddyhttp/proxy/proxy_test.go index 62c4118c5..e13a3d465 100644 --- a/caddyhttp/proxy/proxy_test.go +++ b/caddyhttp/proxy/proxy_test.go @@ -687,6 +687,10 @@ func (u *fakeUpstream) AllowedPath(requestPath string) bool { return true } +func (u *fakeUpstream) Transparent() bool { + return true +} + // newWebSocketTestProxy returns a test proxy that will // redirect to the specified backendAddr. The function // also sets up the rules/environment for testing WebSocket @@ -729,6 +733,10 @@ func (u *fakeWsUpstream) AllowedPath(requestPath string) bool { return true } +func (u *fakeWsUpstream) Transparent() bool { + return true +} + // recorderHijacker is a ResponseRecorder that can // be hijacked. type recorderHijacker struct { diff --git a/caddyhttp/proxy/upstream.go b/caddyhttp/proxy/upstream.go index a2f75fa88..67ca09573 100644 --- a/caddyhttp/proxy/upstream.go +++ b/caddyhttp/proxy/upstream.go @@ -102,10 +102,6 @@ func NewStaticUpstreams(c caddyfile.Dispenser) ([]Upstream, error) { upstream.Hosts[i] = uh } - if upstream.transparent { - upstream.upstreamHeaders.Add("Host", upstream.Hosts[0].Name) - } - if upstream.HealthCheck.Path != "" { upstream.HealthCheck.Client = http.Client{ Timeout: upstream.HealthCheck.Timeout, @@ -372,6 +368,11 @@ func (u *staticUpstream) Select() *UpstreamHost { return u.Policy.Select(pool) } +// Transparent returns true if upstream in transparent mode +func (u *staticUpstream) Transparent() bool { + return u.transparent +} + func (u *staticUpstream) AllowedPath(requestPath string) bool { for _, ignoredSubPath := range u.IgnoredSubPaths { if httpserver.Path(path.Clean(requestPath)).Matches(path.Join(u.From(), ignoredSubPath)) { diff --git a/caddyhttp/proxy/upstream_test.go b/caddyhttp/proxy/upstream_test.go index 02e2c605e..5431962e6 100644 --- a/caddyhttp/proxy/upstream_test.go +++ b/caddyhttp/proxy/upstream_test.go @@ -209,12 +209,8 @@ func TestParseBlock(t *testing.T) { for _, upstream := range upstreams { headers := upstream.Select().UpstreamHeaders - if _, ok := headers["Host"]; !ok { - t.Errorf("Test %d: Could not find the Host header", i+1) - } - - if v, _ := headers["Host"]; v[0] != upstream.Select().Name { - t.Errorf("Test %d: Host not match first hostname in upstream", i+1) + if !upstream.Transparent() { + t.Errorf("Test %d: Upstream should be in transparent mode", i+1) } if _, ok := headers["X-Real-Ip"]; !ok {