diff --git a/src/code.cloudfoundry.org/gorouter/proxy/proxy.go b/src/code.cloudfoundry.org/gorouter/proxy/proxy.go index 6bc0e5392..d30ff9f7c 100644 --- a/src/code.cloudfoundry.org/gorouter/proxy/proxy.go +++ b/src/code.cloudfoundry.org/gorouter/proxy/proxy.go @@ -142,11 +142,16 @@ func NewProxy( rproxy := &httputil.ReverseProxy{ Rewrite: func(r *httputil.ProxyRequest) { p.setupProxyRequest(r.Out) - // Rewrite mode strips X-Forwarded-* from r.Out before calling this - // function. Restore them to replicate the behavior Director had: + // Rewrite mode strips the Forwarded and X-Forwarded-* headers from + // r.Out before calling this function. Restore them to replicate the + // behavior Director had: + // - Forwarded: pass the client-supplied value(s) through verbatim. // - X-Forwarded-Proto: copy the value already set by the XForwardedProto middleware. // - X-Forwarded-Host: preserve whatever the client/middleware set. // - X-Forwarded-For: append the client IP from r.In.RemoteAddr. + if fwd := r.In.Header.Values("Forwarded"); len(fwd) > 0 { + r.Out.Header["Forwarded"] = append([]string(nil), fwd...) + } if proto := r.In.Header.Get("X-Forwarded-Proto"); proto != "" { r.Out.Header.Set("X-Forwarded-Proto", proto) } diff --git a/src/code.cloudfoundry.org/gorouter/proxy/proxy_test.go b/src/code.cloudfoundry.org/gorouter/proxy/proxy_test.go index b5a703da4..9f1c5762c 100644 --- a/src/code.cloudfoundry.org/gorouter/proxy/proxy_test.go +++ b/src/code.cloudfoundry.org/gorouter/proxy/proxy_test.go @@ -498,6 +498,24 @@ var _ = Describe("Proxy", func() { }) }) + Describe("Forwarded", func() { + It("passes a client-supplied Forwarded header through verbatim", func() { + req.Header.Set("Forwarded", "for=1.2.3.4;proto=https;host=example.com") + Expect(getProxiedHeaders(req).Get("Forwarded")).To(Equal("for=1.2.3.4;proto=https;host=example.com")) + }) + + It("preserves multiple Forwarded header values", func() { + req.Header.Add("Forwarded", "for=1.2.3.4") + req.Header.Add("Forwarded", "for=5.6.7.8") + Expect(getProxiedHeaders(req).Values("Forwarded")).To(Equal([]string{"for=1.2.3.4", "for=5.6.7.8"})) + }) + + It("does not add a Forwarded header when the client does not send one", func() { + _, ok := getProxiedHeaders(req)["Forwarded"] + Expect(ok).To(BeFalse()) + }) + }) + Describe("X-Forwarded-Host", func() { Context("for expect-100-continue requests", func() { It("preserves the X-Forwarded-Host header", func() {