Case insensitive Content-Encoding check
Fixes a problem with a header in the response containing content-encoding in lowercase letters. Uses HttpHeaders for case insensitve check. Also fixes an issue checking if a request is made for gzip content. If headers has more than gzip (ie gzip,deflate,sdch), checks if contains gzip instead of equals to. Fixes gh-662
This commit is contained in:
committed by
Spencer Gibb
parent
a61c18c69c
commit
f707e5f053
@@ -43,6 +43,9 @@ import com.netflix.zuul.util.HTTPRequestUtils;
|
||||
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
import static org.springframework.http.HttpHeaders.CONTENT_ENCODING;
|
||||
import static org.springframework.http.HttpHeaders.CONTENT_LENGTH;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@@ -55,8 +58,6 @@ public class ProxyRequestHelper {
|
||||
*/
|
||||
public static final String IGNORED_HEADERS = "ignoredHeaders";
|
||||
|
||||
public static final String CONTENT_ENCODING = "Content-Encoding";
|
||||
|
||||
private TraceRepository traces;
|
||||
|
||||
public void setTraces(TraceRepository traces) {
|
||||
@@ -122,15 +123,23 @@ public class ProxyRequestHelper {
|
||||
}
|
||||
|
||||
public void setResponse(int status, InputStream entity,
|
||||
MultiValueMap<String, String> headers) throws IOException {
|
||||
MultiValueMap<String, String> headers) throws IOException {
|
||||
RequestContext context = RequestContext.getCurrentContext();
|
||||
RequestContext.getCurrentContext().setResponseStatusCode(status);
|
||||
context.setResponseStatusCode(status);
|
||||
if (entity != null) {
|
||||
RequestContext.getCurrentContext().setResponseDataStream(entity);
|
||||
context.setResponseDataStream(entity);
|
||||
}
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
for (Entry<String, List<String>> header : headers.entrySet()) {
|
||||
List<String> values = header.getValue();
|
||||
for (String value : values) {
|
||||
httpHeaders.add(header.getKey(), value);
|
||||
}
|
||||
}
|
||||
boolean isOriginResponseGzipped = false;
|
||||
if (headers.containsKey(CONTENT_ENCODING)) {
|
||||
Collection<String> collection = headers.get(CONTENT_ENCODING);
|
||||
if (httpHeaders.containsKey(CONTENT_ENCODING)) {
|
||||
List<String> collection = httpHeaders.get(CONTENT_ENCODING);
|
||||
for (String header : collection) {
|
||||
if (HTTPRequestUtils.getInstance().isGzipped(header)) {
|
||||
isOriginResponseGzipped = true;
|
||||
@@ -139,16 +148,16 @@ public class ProxyRequestHelper {
|
||||
}
|
||||
}
|
||||
context.setResponseGZipped(isOriginResponseGzipped);
|
||||
|
||||
for (Entry<String, List<String>> header : headers.entrySet()) {
|
||||
RequestContext ctx = RequestContext.getCurrentContext();
|
||||
String name = header.getKey();
|
||||
for (String value : header.getValue()) {
|
||||
ctx.addOriginResponseHeader(name, value);
|
||||
if (name.equalsIgnoreCase("content-length")) {
|
||||
ctx.setOriginContentLength(value);
|
||||
context.addOriginResponseHeader(name, value);
|
||||
if (name.equalsIgnoreCase(CONTENT_LENGTH)) {
|
||||
context.setOriginContentLength(value);
|
||||
}
|
||||
if (isIncludedHeader(name)) {
|
||||
ctx.addZuulResponseHeader(name, value);
|
||||
context.addZuulResponseHeader(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,21 +185,21 @@ public class ProxyRequestHelper {
|
||||
}
|
||||
}
|
||||
switch (name) {
|
||||
case "host":
|
||||
case "connection":
|
||||
case "content-length":
|
||||
case "content-encoding":
|
||||
case "server":
|
||||
case "transfer-encoding":
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
case "host":
|
||||
case "connection":
|
||||
case "content-length":
|
||||
case "content-encoding":
|
||||
case "server":
|
||||
case "transfer-encoding":
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> debug(String verb, String uri,
|
||||
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
|
||||
InputStream requestEntity) throws IOException {
|
||||
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
|
||||
InputStream requestEntity) throws IOException {
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>();
|
||||
if (this.traces != null) {
|
||||
RequestContext context = RequestContext.getCurrentContext();
|
||||
@@ -233,7 +242,7 @@ public class ProxyRequestHelper {
|
||||
}
|
||||
|
||||
public void appendDebug(Map<String, Object> info, int status,
|
||||
MultiValueMap<String, String> headers) {
|
||||
MultiValueMap<String, String> headers) {
|
||||
if (this.traces != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> trace = (Map<String, Object>) info.get("headers");
|
||||
@@ -267,3 +276,4 @@ public class ProxyRequestHelper {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -35,10 +34,14 @@ import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.constants.ZuulConstants;
|
||||
import com.netflix.zuul.constants.ZuulHeaders;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.netflix.zuul.util.HTTPRequestUtils;
|
||||
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@CommonsLog
|
||||
public class SendResponseFilter extends ZuulFilter {
|
||||
|
||||
private static DynamicBooleanProperty INCLUDE_DEBUG_HEADER = DynamicPropertyFactory
|
||||
@@ -101,7 +104,9 @@ public class SendResponseFilter extends ZuulFilter {
|
||||
boolean isGzipRequested = false;
|
||||
final String requestEncoding = context.getRequest().getHeader(
|
||||
ZuulHeaders.ACCEPT_ENCODING);
|
||||
if (requestEncoding != null && requestEncoding.equals("gzip")) {
|
||||
|
||||
if (requestEncoding != null
|
||||
&& HTTPRequestUtils.getInstance().isGzipped(requestEncoding)) {
|
||||
isGzipRequested = true;
|
||||
}
|
||||
is = context.getResponseDataStream();
|
||||
@@ -117,8 +122,8 @@ public class SendResponseFilter extends ZuulFilter {
|
||||
inputStream = new GZIPInputStream(is);
|
||||
}
|
||||
catch (java.util.zip.ZipException ex) {
|
||||
System.out.println("gzip expected but not "
|
||||
+ "received assuming unencoded response"
|
||||
log.debug("gzip expected but not "
|
||||
+ "received assuming unencoded response "
|
||||
+ RequestContext.getCurrentContext().getRequest()
|
||||
.getRequestURL().toString());
|
||||
inputStream = is;
|
||||
|
||||
@@ -16,15 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.netflix.zuul.filters;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -33,12 +25,24 @@ import org.mockito.Mock;
|
||||
import org.springframework.boot.actuate.trace.InMemoryTraceRepository;
|
||||
import org.springframework.boot.actuate.trace.Trace;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@@ -71,7 +75,7 @@ public class ProxyRequestHelperTests {
|
||||
new LinkedMultiValueMap<String, String>(), request.getInputStream());
|
||||
Trace actual = this.traceRepository.findAll().get(0);
|
||||
System.err.println(actual.getInfo());
|
||||
assertThat((String)actual.getInfo().get("body"), equalTo("{}"));
|
||||
assertThat((String) actual.getInfo().get("body"), equalTo("{}"));
|
||||
|
||||
}
|
||||
|
||||
@@ -112,4 +116,45 @@ public class ProxyRequestHelperTests {
|
||||
assertThat(acceptEncodings, contains("gzip"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setResponseLowercase() throws IOException {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RequestContext context = RequestContext.getCurrentContext();
|
||||
context.setRequest(request);
|
||||
context.setResponse(response);
|
||||
|
||||
ProxyRequestHelper helper = new ProxyRequestHelper();
|
||||
|
||||
MultiValueMap<String, String> headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_ENCODING.toLowerCase(), "gzip");
|
||||
|
||||
helper.setResponse(
|
||||
200,
|
||||
request.getInputStream(),
|
||||
headers);
|
||||
assertTrue(context.getResponseGZipped());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setResponseUppercase() throws IOException {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RequestContext context = RequestContext.getCurrentContext();
|
||||
context.setRequest(request);
|
||||
context.setResponse(response);
|
||||
|
||||
ProxyRequestHelper helper = new ProxyRequestHelper();
|
||||
|
||||
MultiValueMap<String, String> headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_ENCODING, "gzip");
|
||||
|
||||
helper.setResponse(
|
||||
200,
|
||||
request.getInputStream(),
|
||||
headers);
|
||||
assertTrue(context.getResponseGZipped());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user