From 46e1d280707788a4043e935c48c5b3d0ea2a5f6f Mon Sep 17 00:00:00 2001 From: Josh Hawn Date: Fri, 24 Apr 2015 14:04:48 -0700 Subject: [PATCH] Updated urlbuilder X-Forwarded-Host logic According to the Apache mod_proxy docs, X-Forwarded-Host can be a comma-separated list of hosts, to which each proxy appends the requested host. We want to grab only the first from this comma-separated list to get the original requested Host when building URLs. Docker-DCO-1.1-Signed-off-by: Josh Hawn (github: jlhawn) --- registry/api/v2/urls.go | 7 ++++++- registry/api/v2/urls_test.go | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/registry/api/v2/urls.go b/registry/api/v2/urls.go index 4b42dd16..60aad565 100644 --- a/registry/api/v2/urls.go +++ b/registry/api/v2/urls.go @@ -62,7 +62,12 @@ func NewURLBuilderFromRequest(r *http.Request) *URLBuilder { host := r.Host forwardedHost := r.Header.Get("X-Forwarded-Host") if len(forwardedHost) > 0 { - host = forwardedHost + // According to the Apache mod_proxy docs, X-Forwarded-Host can be a + // comma-separated list of hosts, to which each proxy appends the + // requested host. We want to grab the first from this comma-separated + // list. + hosts := strings.SplitN(forwardedHost, ",", 2) + host = strings.TrimSpace(hosts[0]) } basePath := routeDescriptorsMap[RouteNameBase].Path diff --git a/registry/api/v2/urls_test.go b/registry/api/v2/urls_test.go index 237d0f61..1113a7dd 100644 --- a/registry/api/v2/urls_test.go +++ b/registry/api/v2/urls_test.go @@ -151,6 +151,12 @@ func TestBuilderFromRequest(t *testing.T) { forwardedProtoHeader := make(http.Header, 1) forwardedProtoHeader.Set("X-Forwarded-Proto", "https") + forwardedHostHeader1 := make(http.Header, 1) + forwardedHostHeader1.Set("X-Forwarded-Host", "first.example.com") + + forwardedHostHeader2 := make(http.Header, 1) + forwardedHostHeader2.Set("X-Forwarded-Host", "first.example.com, proxy1.example.com") + testRequests := []struct { request *http.Request base string @@ -163,6 +169,14 @@ func TestBuilderFromRequest(t *testing.T) { request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader}, base: "https://example.com", }, + { + request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader1}, + base: "http://first.example.com", + }, + { + request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader2}, + base: "http://first.example.com", + }, } for _, tr := range testRequests {