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 2c9d301e..6db078a9 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 @@ -124,23 +124,29 @@ public class PreDecorationFilter extends ZuulFilter { String.valueOf(ctx.getRequest().getServerPort())); ctx.addZuulRequestHeader(ZuulHeaders.X_FORWARDED_PROTO, ctx.getRequest().getScheme()); + String forwardedPrefix = + ctx.getRequest().getHeader("X-Forwarded-Prefix"); + String contextPath = ctx.getRequest().getContextPath(); + String prefix = StringUtils.hasLength(forwardedPrefix) + ? forwardedPrefix + : (StringUtils.hasLength(contextPath) ? contextPath : null); if (StringUtils.hasText(route.getPrefix())) { - String existingPrefix = ctx.getRequest() - .getHeader("X-Forwarded-Prefix"); StringBuilder newPrefixBuilder = new StringBuilder(); - if (StringUtils.hasLength(existingPrefix)) { - if (existingPrefix.endsWith("/") + if (prefix != null) { + if (prefix.endsWith("/") && route.getPrefix().startsWith("/")) { - newPrefixBuilder.append(existingPrefix, 0, - existingPrefix.length() - 1); + newPrefixBuilder.append(prefix, 0, + prefix.length() - 1); } else { - newPrefixBuilder.append(existingPrefix); + newPrefixBuilder.append(prefix); } } newPrefixBuilder.append(route.getPrefix()); - ctx.addZuulRequestHeader("X-Forwarded-Prefix", - newPrefixBuilder.toString()); + prefix = newPrefixBuilder.toString(); + } + if (prefix != null) { + ctx.addZuulRequestHeader("X-Forwarded-Prefix", prefix); } String xforwardedfor = ctx.getRequest().getHeader("X-Forwarded-For"); String remoteAddr = ctx.getRequest().getRemoteAddr(); 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 71a3a539..940634ff 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 @@ -164,6 +164,86 @@ public class PreDecorationFilterTests { getHeader(ctx.getOriginResponseHeaders(), "x-zuul-serviceid")); } + @Test + public void routeWithContextPath() { + this.properties.setStripPrefix(false); + this.request.setRequestURI("/api/foo/1"); + this.request.setContextPath("/context-path"); + this.routeLocator.addRoute( + new ZuulRoute("foo", "/api/foo/**", "foo", null, false, null, null)); + this.filter.run(); + RequestContext ctx = RequestContext.getCurrentContext(); + assertEquals("/api/foo/1", ctx.get("requestURI")); + assertEquals("localhost", ctx.getZuulRequestHeaders().get("x-forwarded-host")); + assertEquals("80", ctx.getZuulRequestHeaders().get("x-forwarded-port")); + assertEquals("http", ctx.getZuulRequestHeaders().get("x-forwarded-proto")); + assertEquals("/context-path", + ctx.getZuulRequestHeaders().get("x-forwarded-prefix")); + assertEquals("foo", + getHeader(ctx.getOriginResponseHeaders(), "x-zuul-serviceid")); + } + + @Test + public void prefixRouteWithContextPath() { + this.properties.setPrefix("/api"); + this.properties.setStripPrefix(true); + this.request.setRequestURI("/api/foo/1"); + this.request.setContextPath("/context-path"); + this.routeLocator.addRoute( + new ZuulRoute("foo", "/foo/**", "foo", null, false, null, null)); + this.filter.run(); + RequestContext ctx = RequestContext.getCurrentContext(); + assertEquals("/foo/1", ctx.get("requestURI")); + assertEquals("localhost", ctx.getZuulRequestHeaders().get("x-forwarded-host")); + assertEquals("80", ctx.getZuulRequestHeaders().get("x-forwarded-port")); + assertEquals("http", ctx.getZuulRequestHeaders().get("x-forwarded-proto")); + assertEquals("/context-path/api", + ctx.getZuulRequestHeaders().get("x-forwarded-prefix")); + assertEquals("foo", + getHeader(ctx.getOriginResponseHeaders(), "x-zuul-serviceid")); + } + + @Test + public void routeIgnoreContextPathIfPrefixHeader() { + this.properties.setStripPrefix(false); + this.request.setRequestURI("/api/foo/1"); + this.request.setContextPath("/context-path"); + this.request.addHeader("X-Forwarded-Prefix", "/prefix"); + this.routeLocator.addRoute( + new ZuulRoute("foo", "/api/foo/**", "foo", null, false, null, null)); + this.filter.run(); + RequestContext ctx = RequestContext.getCurrentContext(); + assertEquals("/api/foo/1", ctx.get("requestURI")); + assertEquals("localhost", ctx.getZuulRequestHeaders().get("x-forwarded-host")); + assertEquals("80", ctx.getZuulRequestHeaders().get("x-forwarded-port")); + assertEquals("http", ctx.getZuulRequestHeaders().get("x-forwarded-proto")); + assertEquals("/prefix", + ctx.getZuulRequestHeaders().get("x-forwarded-prefix")); + assertEquals("foo", + getHeader(ctx.getOriginResponseHeaders(), "x-zuul-serviceid")); + } + + @Test + public void prefixRouteIgnoreContextPathIfPrefixHeader() { + this.properties.setPrefix("/api"); + this.properties.setStripPrefix(true); + this.request.setRequestURI("/api/foo/1"); + this.request.setContextPath("/context-path"); + this.request.addHeader("X-Forwarded-Prefix", "/prefix"); + this.routeLocator.addRoute( + new ZuulRoute("foo", "/foo/**", "foo", null, false, null, null)); + this.filter.run(); + RequestContext ctx = RequestContext.getCurrentContext(); + assertEquals("/foo/1", ctx.get("requestURI")); + assertEquals("localhost", ctx.getZuulRequestHeaders().get("x-forwarded-host")); + assertEquals("80", ctx.getZuulRequestHeaders().get("x-forwarded-port")); + assertEquals("http", ctx.getZuulRequestHeaders().get("x-forwarded-proto")); + assertEquals("/prefix/api", + ctx.getZuulRequestHeaders().get("x-forwarded-prefix")); + assertEquals("foo", + getHeader(ctx.getOriginResponseHeaders(), "x-zuul-serviceid")); + } + @Test public void forwardRouteAddsLocation() throws Exception { this.properties.setPrefix("/api"); @@ -405,7 +485,7 @@ public class PreDecorationFilterTests { assertTrue("sensitiveHeaders is wrong: " + sensitiveHeaders, sensitiveHeaders.containsAll(Arrays.asList("x-bar", "x-foo"))); } - + @Test public void urlProperlyDecodedWhenCharacterEncodingIsSet() throws Exception { this.request.setCharacterEncoding("UTF-8");