diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java index 3bdb633b..9d3278df 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java @@ -82,6 +82,11 @@ public class ZuulProperties { */ private boolean addProxyHeaders = true; + /** + * Flag to determine whether the proxy forwards the Host header. + */ + private boolean addHostHeader = false; + /** * Set of service names not to consider for proxying automatically. By default all * services in the discovery client will be proxied. diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java index 39dc918b..2c9d301e 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java @@ -19,6 +19,8 @@ package org.springframework.cloud.netflix.zuul.filters.pre; import java.net.MalformedURLException; import java.net.URL; +import javax.servlet.http.HttpServletRequest; + import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; import org.springframework.cloud.netflix.zuul.filters.Route; import org.springframework.cloud.netflix.zuul.filters.RouteLocator; @@ -36,6 +38,8 @@ import lombok.extern.apachecommons.CommonsLog; @CommonsLog public class PreDecorationFilter extends ZuulFilter { + public static final int FILTER_ORDER = 5; + private RouteLocator routeLocator; private String dispatcherServletPath; @@ -58,7 +62,7 @@ public class PreDecorationFilter extends ZuulFilter { @Override public int filterOrder() { - return 5; + return FILTER_ORDER; } @Override @@ -115,8 +119,7 @@ public class PreDecorationFilter extends ZuulFilter { ctx.addOriginResponseHeader("X-Zuul-ServiceId", location); } if (this.properties.isAddProxyHeaders()) { - ctx.addZuulRequestHeader("X-Forwarded-Host", - ctx.getRequest().getServerName()); + ctx.addZuulRequestHeader("X-Forwarded-Host", toHostHeader(ctx.getRequest())); ctx.addZuulRequestHeader("X-Forwarded-Port", String.valueOf(ctx.getRequest().getServerPort())); ctx.addZuulRequestHeader(ZuulHeaders.X_FORWARDED_PROTO, @@ -149,6 +152,9 @@ public class PreDecorationFilter extends ZuulFilter { } ctx.addZuulRequestHeader("X-Forwarded-For", xforwardedfor); } + if (this.properties.isAddHostHeader()) { + ctx.addZuulRequestHeader("Host", toHostHeader(ctx.getRequest())); + } } } else { @@ -182,6 +188,15 @@ public class PreDecorationFilter extends ZuulFilter { return null; } + private String toHostHeader(HttpServletRequest request) { + int port = request.getServerPort(); + if ((port == 80 && "http".equals(request.getScheme())) || (port == 443 && "https".equals(request.getScheme()))) { + return request.getServerName(); + } else { + return request.getServerName() + ":" + port; + } + } + private URL getUrl(String target) { try { return new URL(target); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java index 9b521676..71a3a539 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java @@ -90,6 +90,34 @@ public class PreDecorationFilterTests { assertEquals(false, this.filter.shouldFilter()); } + @Test + public void xForwardedHostHasPort() throws Exception { + this.properties.setPrefix("/api"); + this.request.setRequestURI("/api/foo/1"); + this.request.setRemoteAddr("5.6.7.8"); + this.request.setServerPort(8080); + this.routeLocator.addRoute( + new ZuulRoute("foo", "/foo/**", "foo", null, false, null, null)); + this.filter.run(); + RequestContext ctx = RequestContext.getCurrentContext(); + assertEquals("localhost:8080", ctx.getZuulRequestHeaders().get("x-forwarded-host")); + } + + @Test + public void hostHeaderSet() throws Exception { + this.properties.setPrefix("/api"); + this.properties.setAddHostHeader(true); + this.request.setRequestURI("/api/foo/1"); + this.request.setRemoteAddr("5.6.7.8"); + this.request.setServerPort(8080); + this.routeLocator.addRoute( + new ZuulRoute("foo", "/foo/**", "foo", null, false, null, null)); + this.filter.run(); + RequestContext ctx = RequestContext.getCurrentContext(); + assertEquals("localhost:8080", ctx.getZuulRequestHeaders().get("x-forwarded-host")); + assertEquals("localhost:8080", ctx.getZuulRequestHeaders().get("host")); + } + @Test public void prefixRouteAddsHeader() throws Exception { this.properties.setPrefix("/api");