mirror of
https://github.com/spring-cloud/spring-cloud-netflix.git
synced 2026-09-21 01:59:01 +00:00
Always forward Content-Length header from origin when set (#2833)
* Always forward Content-Length from origin when set unless response is compressed and client does not support it Fix for #2832 * Add test cases to assert behaviour with regards to the Content-Length header
This commit is contained in:
committed by
Ryan Baxter
parent
2118d5b4dd
commit
406e112aaa
+26
-11
@@ -240,18 +240,14 @@ public class SendResponseFilter extends ZuulFilter {
|
||||
servletResponse.addHeader(it.first(), it.second());
|
||||
}
|
||||
}
|
||||
// Only inserts Content-Length if origin provides it and origin response is not
|
||||
// gzipped
|
||||
if (this.zuulProperties.isSetContentLength()) {
|
||||
if (includeContentLengthHeader(context)) {
|
||||
Long contentLength = context.getOriginContentLength();
|
||||
if ( contentLength != null && !context.getResponseGZipped()) {
|
||||
if(useServlet31) {
|
||||
servletResponse.setContentLengthLong(contentLength);
|
||||
} else {
|
||||
//Try and set some kind of content length if we can safely convert the Long to an int
|
||||
if (isLongSafe(contentLength)) {
|
||||
servletResponse.setContentLength(contentLength.intValue());
|
||||
}
|
||||
if(useServlet31) {
|
||||
servletResponse.setContentLengthLong(contentLength);
|
||||
} else {
|
||||
//Try and set some kind of content length if we can safely convert the Long to an int
|
||||
if (isLongSafe(contentLength)) {
|
||||
servletResponse.setContentLength(contentLength.intValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,4 +257,23 @@ public class SendResponseFilter extends ZuulFilter {
|
||||
return value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
protected boolean includeContentLengthHeader(RequestContext context) {
|
||||
// Not configured to forward the header
|
||||
if (!this.zuulProperties.isSetContentLength()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only if Content-Length is provided
|
||||
if (context.getOriginContentLength() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If response is compressed, include header only if we are not about to decompress it
|
||||
if (context.getResponseGZipped()) {
|
||||
return context.isGzipRequested();
|
||||
}
|
||||
|
||||
// Forward it in all other cases
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+44
-2
@@ -36,6 +36,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import com.netflix.zuul.constants.ZuulHeaders;
|
||||
import com.netflix.zuul.context.Debug;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
|
||||
@@ -61,6 +62,7 @@ public class SendResponseFilterTests {
|
||||
@Before
|
||||
public void setTestRequestcontext() {
|
||||
RequestContext context = new RequestContext();
|
||||
context.setResponseGZipped(false);
|
||||
RequestContext.testSetCurrentContext(context);
|
||||
}
|
||||
|
||||
@@ -102,6 +104,9 @@ public class SendResponseFilterTests {
|
||||
assertThat("wrong debug header", debugHeader, equalTo("[[[test]]]"));
|
||||
}
|
||||
|
||||
/*
|
||||
* GZip NOT requested and NOT a GZip response -> Content-Length forwarded asis
|
||||
*/
|
||||
@Test
|
||||
public void runWithOriginContentLength() throws Exception {
|
||||
ZuulProperties properties = new ZuulProperties();
|
||||
@@ -117,6 +122,42 @@ public class SendResponseFilterTests {
|
||||
assertThat("wrong origin content length", contentLength, equalTo("6"));
|
||||
}
|
||||
|
||||
/*
|
||||
* GZip requested and GZip response -> Content-Length forwarded asis
|
||||
*/
|
||||
@Test
|
||||
public void runWithOriginContentLength_gzipRequested_gzipResponse() throws Exception {
|
||||
ZuulProperties properties = new ZuulProperties();
|
||||
properties.setSetContentLength(true);
|
||||
|
||||
SendResponseFilter filter = createFilter(properties, "hello", "UTF-8", new MockHttpServletResponse(), true);
|
||||
RequestContext.getCurrentContext().setOriginContentLength(6L); // for test
|
||||
RequestContext.getCurrentContext().setResponseGZipped(true);
|
||||
((MockHttpServletRequest) RequestContext.getCurrentContext().getRequest()).addHeader(ZuulHeaders.ACCEPT_ENCODING, "gzip");
|
||||
|
||||
filter.run();
|
||||
|
||||
String contentLength = RequestContext.getCurrentContext().getResponse().getHeader("Content-Length");
|
||||
assertThat("wrong origin content length", contentLength, equalTo("6"));
|
||||
}
|
||||
|
||||
/*
|
||||
* GZip NOT requested and GZip response -> Content-Length discarded
|
||||
*/
|
||||
@Test
|
||||
public void runWithOriginContentLength_gzipNotRequested_gzipResponse() throws Exception {
|
||||
ZuulProperties properties = new ZuulProperties();
|
||||
properties.setSetContentLength(true);
|
||||
|
||||
SendResponseFilter filter = createFilter(properties, "hello", "UTF-8", new MockHttpServletResponse(), true);
|
||||
RequestContext.getCurrentContext().setOriginContentLength(6L); // for test
|
||||
RequestContext.getCurrentContext().setResponseGZipped(true);
|
||||
|
||||
filter.run();
|
||||
|
||||
assertThat(RequestContext.getCurrentContext().getResponse().getHeader("Content-Length")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeResponseOutputStreamError() throws Exception {
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
@@ -126,6 +167,7 @@ public class SendResponseFilterTests {
|
||||
context.setRequest(new MockHttpServletRequest());
|
||||
context.setResponse(response);
|
||||
context.setResponseDataStream(mockStream);
|
||||
context.setResponseGZipped(false);
|
||||
Closeable zuulResponse = mock(Closeable.class);
|
||||
context.set("zuulResponse", zuulResponse);
|
||||
RequestContext.testSetCurrentContext(context);
|
||||
@@ -156,6 +198,7 @@ public class SendResponseFilterTests {
|
||||
context.setRequest(new MockHttpServletRequest());
|
||||
context.setResponse(response);
|
||||
context.setResponseDataStream(mockStream);
|
||||
context.setResponseGZipped(false);
|
||||
Closeable zuulResponse = mock(Closeable.class);
|
||||
context.set("zuulResponse", zuulResponse);
|
||||
RequestContext.testSetCurrentContext(context);
|
||||
@@ -200,8 +243,7 @@ public class SendResponseFilterTests {
|
||||
context.setResponseBody(content);
|
||||
}
|
||||
|
||||
context.addZuulResponseHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(content.length()));
|
||||
|
||||
context.setResponseGZipped(false);
|
||||
context.set("error.status_code", HttpStatus.NOT_FOUND.value());
|
||||
RequestContext.testSetCurrentContext(context);
|
||||
SendResponseFilter filter = new SendResponseFilter(properties);
|
||||
|
||||
Reference in New Issue
Block a user