diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java index 1fc153d79..d91d3d7f3 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java @@ -29,6 +29,7 @@ import java.util.Set; import javax.servlet.http.HttpServletRequest; +import lombok.extern.apachecommons.CommonsLog; import org.apache.commons.io.IOUtils; import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.util.LinkedMultiValueMap; @@ -37,10 +38,13 @@ import org.springframework.util.StringUtils; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.util.HTTPRequestUtils; +import org.springframework.web.util.UriUtils; +import org.springframework.web.util.WebUtils; /** * @author Dave Syer */ +@CommonsLog public class ProxyRequestHelper { /** @@ -57,6 +61,20 @@ public class ProxyRequestHelper { this.traces = traces; } + public String buildZuulRequestURI(HttpServletRequest request) { + RequestContext context = RequestContext.getCurrentContext(); + String uri = request.getRequestURI(); + String contextURI = (String) context.get("requestURI"); + if (contextURI != null) { + try { + uri = UriUtils.encodePath(contextURI, WebUtils.DEFAULT_CHARACTER_ENCODING); + } catch (Exception e) { + log.debug("unable to encode uri path from context, falling back to uri from request", e); + } + } + return uri; + } + public MultiValueMap buildZuulRequestQueryParams( HttpServletRequest request) { Map> map = HTTPRequestUtils.getInstance().getQueryParams(); diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommand.java index 4033fc068..d8b0b7177 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonCommand.java @@ -80,7 +80,7 @@ public class RibbonCommand extends HystrixCommand { super(getSetter(commandKey)); this.restClient = restClient; this.verb = verb; - this.uri = (StringUtils.hasText(uri))? UriComponentsBuilder.fromUriString(uri).build().toUri() : new URI(uri); + this.uri = new URI(uri); this.retryable = retryable; this.headers = headers; this.params = params; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java index e1e900624..ebdf2baf9 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java @@ -95,10 +95,8 @@ public class RibbonRoutingFilter extends ZuulFilter { RestClient restClient = this.clientFactory.getClient(serviceId, RestClient.class); - String uri = request.getRequestURI(); - if (context.get("requestURI") != null) { - uri = (String) context.get("requestURI"); - } + String uri = this.helper.buildZuulRequestURI(request); + // remove double slashes uri = uri.replace("//", "/"); String service = (String) context.get("serviceId"); diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java index cb2906345..cc534ec4e 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java @@ -168,10 +168,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter { InputStream requestEntity = getRequestBody(request); HttpClient httpclient = CLIENT.get(); - String uri = request.getRequestURI(); - if (context.get("requestURI") != null) { - uri = (String) context.get("requestURI"); - } + String uri = this.helper.buildZuulRequestURI(request); try { HttpResponse response = forward(httpclient, verb, uri, request, headers, diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/SampleZuulProxyApplicationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/SampleZuulProxyApplicationTests.java index fc7aa12bd..d1e7c52ff 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/SampleZuulProxyApplicationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/SampleZuulProxyApplicationTests.java @@ -134,7 +134,7 @@ public class SampleZuulProxyApplicationTests { } @Test - public void routeWithSpace() { + public void ribbonRouteWithSpace() { ResponseEntity result = new TestRestTemplate().exchange( "http://localhost:" + this.port + "/simple/spa ce", HttpMethod.GET, new HttpEntity<>((Void) null), String.class); @@ -142,6 +142,17 @@ public class SampleZuulProxyApplicationTests { assertEquals("Hello space", result.getBody()); } + @Test + public void simpleHostRouteWithSpace() { + routes.addRoute("/self/**", "http://localhost:" + this.port); + this.endpoint.reset(); + ResponseEntity result = new TestRestTemplate().exchange( + "http://localhost:" + this.port + "/self/spa ce", + HttpMethod.GET, new HttpEntity<>((Void) null), String.class); + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals("Hello space", result.getBody()); + } + } // Don't use @SpringBootApplication because we don't want to component scan