diff --git a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java index 58a368d7..794dd33c 100644 --- a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java +++ b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java @@ -63,6 +63,7 @@ import org.springframework.util.StringUtils; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; +import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.REQUEST_ENTITY_KEY; import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE; import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SIMPLE_HOST_ROUTING_FILTER_ORDER; @@ -73,6 +74,7 @@ import static org.springframework.cloud.netflix.zuul.filters.support.FilterConst * @author Spencer Gibb * @author Dave Syer * @author Bilal Alp + * @author Gang Li */ public class SimpleHostRoutingFilter extends ZuulFilter { @@ -338,13 +340,16 @@ public class SimpleHostRoutingFilter extends ZuulFilter { return httpHost; } - private InputStream getRequestBody(HttpServletRequest request) { + protected InputStream getRequestBody(HttpServletRequest request) { InputStream requestEntity = null; try { - requestEntity = request.getInputStream(); + requestEntity = (InputStream) RequestContext.getCurrentContext().get(REQUEST_ENTITY_KEY); + if (requestEntity == null) { + requestEntity = request.getInputStream(); + } } catch (IOException ex) { - // no requestBody is ok. + log.error("error during getRequestBody", ex); } return requestEntity; } diff --git a/spring-cloud-netflix-zuul/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java b/spring-cloud-netflix-zuul/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java index 40fbdb92..1dacf8cc 100644 --- a/spring-cloud-netflix-zuul/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java +++ b/spring-cloud-netflix-zuul/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java @@ -20,7 +20,9 @@ package org.springframework.cloud.netflix.zuul.filters.route; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Field; +import java.net.URL; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; @@ -29,12 +31,14 @@ import java.util.zip.GZIPOutputStream; import javax.servlet.http.HttpServletResponse; +import com.netflix.zuul.context.RequestContext; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.Configurable; +import org.apache.http.client.methods.HttpPatch; import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; @@ -80,6 +84,7 @@ import static org.springframework.util.StreamUtils.copyToString; /** * @author Andreas Kluth * @author Spencer Gibb + * @author Gang Li */ @RunWith(SpringRunner.class) @SpringBootTest(classes = SampleApplication.class, @@ -208,6 +213,88 @@ public class SimpleHostRoutingFilterTests { Assertions.assertThat(httpClient).isNotEqualTo(newhttpClient); } + @Test + public void getRequestBody() throws Exception { + setupContext(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); + request.setContent("{1}".getBytes()); + request.addHeader("singleName", "singleValue"); + request.addHeader("multiName", "multiValue1"); + request.addHeader("multiName", "multiValue2"); + RequestContext.getCurrentContext().setRequest(request); + InputStream inputStream = getFilter().getRequestBody(request); + assertTrue(Arrays.equals("{1}".getBytes(), copyToByteArray(inputStream))); + } + + @Test + public void putRequestBuiltWithBody() throws Exception { + setupContext(); + InputStreamEntity inputStreamEntity = new InputStreamEntity(new ByteArrayInputStream(new byte[]{1})); + HttpRequest httpRequest = getFilter().buildHttpRequest("PUT", "uri", inputStreamEntity, + new LinkedMultiValueMap(), new LinkedMultiValueMap(), new MockHttpServletRequest()); + + assertTrue(httpRequest instanceof HttpEntityEnclosingRequest); + HttpEntityEnclosingRequest httpEntityEnclosingRequest = (HttpEntityEnclosingRequest) httpRequest; + assertTrue(httpEntityEnclosingRequest.getEntity() != null); + } + + @Test + public void postRequestBuiltWithBody() throws Exception { + setupContext(); + InputStreamEntity inputStreamEntity = new InputStreamEntity(new ByteArrayInputStream(new byte[]{1})); + HttpRequest httpRequest = getFilter().buildHttpRequest("POST", "uri", inputStreamEntity, + new LinkedMultiValueMap(), new LinkedMultiValueMap(), new MockHttpServletRequest()); + + assertTrue(httpRequest instanceof HttpEntityEnclosingRequest); + HttpEntityEnclosingRequest httpEntityEnclosingRequest = (HttpEntityEnclosingRequest) httpRequest; + assertTrue(httpEntityEnclosingRequest.getEntity() != null); + } + + @Test + public void pathRequestBuiltWithBody() throws Exception { + setupContext(); + InputStreamEntity inputStreamEntity = new InputStreamEntity(new ByteArrayInputStream(new byte[]{1})); + HttpRequest httpRequest = getFilter().buildHttpRequest("PATCH", "uri", inputStreamEntity, + new LinkedMultiValueMap(), new LinkedMultiValueMap(), new MockHttpServletRequest()); + + HttpPatch basicHttpRequest = (HttpPatch) httpRequest; + assertTrue(basicHttpRequest.getEntity() != null); + } + + @Test + public void shouldFilterFalse() throws Exception { + setupContext(); + assertEquals(false, getFilter().shouldFilter()); + } + + @Test + public void shouldFilterTrue() throws Exception { + setupContext(); + RequestContext.getCurrentContext().set("routeHost", new URL("http://localhost:8080")); + RequestContext.getCurrentContext().set("sendZuulResponse", true); + assertEquals(true, getFilter().shouldFilter()); + } + + @Test + public void filterOrder() throws Exception { + setupContext(); + assertEquals(100, getFilter().filterOrder()); + } + + @Test(expected = IllegalStateException.class) + public void run() throws Exception { + setupContext(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); + request.setContent("{1}".getBytes()); + request.addHeader("singleName", "singleValue"); + request.addHeader("multiName", "multiValue1"); + request.addHeader("multiName", "multiValue2"); + RequestContext.getCurrentContext().setRequest(request); + URL url = new URL("http://localhost:8080"); + RequestContext.getCurrentContext().set("routeHost", url); + getFilter().run(); + } + private void setupContext() { this.context.register(PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);