From 7a90c0cd88e74426d910b192b421d2fcbef4c8e0 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 22 Jun 2016 12:32:57 -0600 Subject: [PATCH] Set entity contentLength to 0 for GET requests. Zuul sets an empty entity for GET requests. The apache http client either sets transfer encoding to chunked or a content length header. This change sets the apache entity contentLength to 0 (not the header), to that in RequestContent the "content-length" header is set to 0 rathern than transfer encoding. See gh-1042 --- .../apache/RibbonApacheHttpRequest.java | 2 + .../apache/RibbonApacheHttpRequestTests.java | 37 ++++++++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequest.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequest.java index ef79c245..598fb9b8 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequest.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequest.java @@ -89,6 +89,8 @@ public class RibbonApacheHttpRequest extends ClientRequest implements Cloneable // to chunked in org.apache.http.protocol.RequestContent. See gh-1042 if (contentLength != null) { entity.setContentLength(this.contentLength); + } else if ("GET".equals(this.method)) { + entity.setContentLength(0); } builder.setEntity(entity); } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequestTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequestTests.java index 0f0e266a..564d8b4c 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequestTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/apache/RibbonApacheHttpRequestTests.java @@ -26,6 +26,7 @@ import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.net.URI; import java.nio.charset.Charset; @@ -61,28 +62,46 @@ public class RibbonApacheHttpRequestTests { assertThat("myparam is missing", request.getURI().getQuery(), is(equalTo("myparam=myparamval"))); } + @Test + // this situation happens, see https://github.com/spring-cloud/spring-cloud-netflix/issues/1042#issuecomment-227723877 + public void testEmptyEntityGet() throws Exception { + String entityValue = ""; + testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), false, "GET"); + } @Test - public void testNotNullEntity() throws Exception { + public void testNonEmptyEntityPost() throws Exception { + String entityValue = "abcd"; + testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), true, "POST"); + } + + void testEntity(String entityValue, ByteArrayInputStream requestEntity, boolean addContentLengthHeader, String method) throws IOException { + String lengthString = String.valueOf(entityValue.length()); + Long length = null; URI uri = URI.create("http://example.com"); LinkedMultiValueMap headers = new LinkedMultiValueMap<>(); - headers.add("Content-Length", "4"); - String entityValue = "abcd"; - RibbonApacheHttpRequest httpRequest = new RibbonApacheHttpRequest("POST", uri, false, - headers, new LinkedMultiValueMap(), new ByteArrayInputStream(entityValue.getBytes()), - (long) entityValue.length()); + if (addContentLengthHeader) { + headers.add("Content-Length", lengthString); + length = (long) entityValue.length(); + } + RibbonApacheHttpRequest httpRequest = new RibbonApacheHttpRequest(method, uri, false, + headers, new LinkedMultiValueMap(), requestEntity, + length); HttpUriRequest request = httpRequest.toRequest(RequestConfig.custom().build()); assertThat("request is wrong type", request, is(instanceOf(HttpEntityEnclosingRequest.class))); assertThat("uri is wrong", request.getURI().toString(), startsWith(uri.toString())); - assertThat("Content-Length is missing", request.getFirstHeader("Content-Length"), is(notNullValue())); - assertThat("Content-Length is wrong", request.getFirstHeader("Content-Length").getValue(), is(equalTo("4"))); + if (addContentLengthHeader) { + assertThat("Content-Length is missing", request.getFirstHeader("Content-Length"), is(notNullValue())); + assertThat("Content-Length is wrong", request.getFirstHeader("Content-Length").getValue(), + is(equalTo(lengthString))); + } HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest) request; assertThat("entity is missing", entityRequest.getEntity(), is(notNullValue())); HttpEntity entity = entityRequest.getEntity(); - assertThat("contentLength is wrong", entity.getContentLength(), is(equalTo(4L))); + assertThat("contentLength is wrong", entity.getContentLength(), is(equalTo((long)entityValue.length()))); assertThat("content is missing", entity.getContent(), is(notNullValue())); String string = StreamUtils.copyToString(entity.getContent(), Charset.forName("UTF-8")); assertThat("content is wrong", string, is(equalTo(entityValue)));