From 238c1329c4417ba953adde3e762722742e8dbcbb Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 15 Dec 2014 13:11:13 +0000 Subject: [PATCH] Remove dependency on jersey for ProxyRequestHelper --- .../cloud/netflix/zuul/ZuulConfiguration.java | 2 +- .../{route => }/ProxyRequestHelper.java | 75 +++++++++++-------- .../filters/route/RibbonRoutingFilter.java | 45 ++++++++--- .../route/SimpleHostRoutingFilter.java | 23 +++--- 4 files changed, 91 insertions(+), 54 deletions(-) rename spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/{route => }/ProxyRequestHelper.java (76%) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java index 37a36685..3e6e320c 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java @@ -10,12 +10,12 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter; import org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter; import org.springframework.cloud.netflix.zuul.filters.pre.DebugFilter; import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter; import org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter; -import org.springframework.cloud.netflix.zuul.filters.route.ProxyRequestHelper; import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter; import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter; import org.springframework.context.annotation.Bean; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/ProxyRequestHelper.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java similarity index 76% rename from spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/ProxyRequestHelper.java rename to spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java index 0ff9fe0e..f95b2759 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/ProxyRequestHelper.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java @@ -13,27 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.netflix.zuul.filters.route; +package org.springframework.cloud.netflix.zuul.filters; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Enumeration; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.MultivaluedMap; import org.apache.commons.io.IOUtils; import org.springframework.boot.actuate.trace.TraceRepository; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.util.HTTPRequestUtils; -import com.sun.jersey.core.util.MultivaluedMapImpl; /** * @author Dave Syer @@ -41,6 +43,12 @@ import com.sun.jersey.core.util.MultivaluedMapImpl; */ public class ProxyRequestHelper { + /** + * Zuul context key for a collection of ignored headers for the current request. + * Pre-filters can set this up as a set of lowercase strings. + */ + public static final String IGNORED_HEADERS = "ignoredHeaders"; + public static final String CONTENT_ENCODING = "Content-Encoding"; private TraceRepository traces; @@ -49,12 +57,12 @@ public class ProxyRequestHelper { this.traces = traces; } - public MultivaluedMap buildZuulRequestQueryParams( + public MultiValueMap buildZuulRequestQueryParams( HttpServletRequest request) { Map> map = HTTPRequestUtils.getInstance().getQueryParams(); - MultivaluedMap params = new MultivaluedMapImpl(); + MultiValueMap params = new LinkedMultiValueMap<>(); if (map == null) return params; @@ -67,34 +75,34 @@ public class ProxyRequestHelper { return params; } - public MultivaluedMap buildZuulRequestHeaders( + public MultiValueMap buildZuulRequestHeaders( HttpServletRequest request) { RequestContext context = RequestContext.getCurrentContext(); - MultivaluedMap headers = new MultivaluedMapImpl(); + MultiValueMap headers = new LinkedMultiValueMap<>(); Enumeration headerNames = request.getHeaderNames(); if (headerNames != null) { while (headerNames.hasMoreElements()) { String name = (String) headerNames.nextElement(); String value = request.getHeader(name); if (isIncludedHeader(name)) - headers.putSingle(name, value); + headers.set(name, value); } } Map zuulRequestHeaders = context.getZuulRequestHeaders(); for (String header : zuulRequestHeaders.keySet()) { - headers.putSingle(header, zuulRequestHeaders.get(header)); + headers.set(header, zuulRequestHeaders.get(header)); } - headers.putSingle("accept-encoding", "deflate, gzip"); + headers.set("accept-encoding", "deflate, gzip"); return headers; } public void setResponse(int status, InputStream entity, - Map> headers) throws IOException { + MultiValueMap headers) throws IOException { RequestContext context = RequestContext.getCurrentContext(); RequestContext.getCurrentContext().setResponseStatusCode(status); @@ -115,7 +123,7 @@ public class ProxyRequestHelper { } context.setResponseGZipped(isOriginResponseGzipped); - for (Entry> header : headers.entrySet()) { + for (Entry> header : headers.entrySet()) { RequestContext ctx = RequestContext.getCurrentContext(); String name = header.getKey(); for (String value : header.getValue()) { @@ -132,8 +140,28 @@ public class ProxyRequestHelper { } + public void addIgnoredHeaders(String... names) { + RequestContext ctx = RequestContext.getCurrentContext(); + if (!ctx.containsKey(IGNORED_HEADERS)) { + ctx.set(IGNORED_HEADERS, new HashSet()); + } + @SuppressWarnings("unchecked") + Set set = (Set) ctx.get(IGNORED_HEADERS); + for (String name : names) { + set.add(name.toLowerCase()); + } + } + public boolean isIncludedHeader(String headerName) { - switch (headerName.toLowerCase()) { + String name = headerName.toLowerCase(); + RequestContext ctx = RequestContext.getCurrentContext(); + if (ctx.containsKey(IGNORED_HEADERS)) { + Object object = ctx.get(IGNORED_HEADERS); + if (object instanceof Collection && ((Collection) object).contains(name)) { + return false; + } + } + switch (name) { case "host": case "connection": case "content-length": @@ -147,9 +175,8 @@ public class ProxyRequestHelper { } public Map debug(String verb, String uri, - MultivaluedMap headers, - MultivaluedMap params, InputStream requestEntity) - throws IOException { + MultiValueMap headers, MultiValueMap params, + InputStream requestEntity) throws IOException { Map info = new LinkedHashMap(); if (traces != null) { @@ -195,14 +222,14 @@ public class ProxyRequestHelper { } public void appendDebug(Map info, int status, - Map> headers) { + MultiValueMap headers) { if (traces != null) { @SuppressWarnings("unchecked") Map trace = (Map) info.get("headers"); Map output = new LinkedHashMap(); trace.put("response", output); info.put("status", "" + status); - for (Entry> key : headers.entrySet()) { + for (Entry> key : headers.entrySet()) { Collection collection = key.getValue(); Object value = collection; if (collection.size() < 2) { @@ -213,18 +240,6 @@ public class ProxyRequestHelper { } } - public void appendDebug(Map info, int status, - MultivaluedMap headers) { - if (traces != null) { - Map> map = new LinkedHashMap>(); - for (Entry> key : headers.entrySet()) { - Collection collection = key.getValue(); - map.put(key.getKey(), collection); - } - appendDebug(info, status, map); - } - } - private void debugRequestEntity(Map info, InputStream inputStream) throws IOException { String entity = IOUtils.toString(inputStream); 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 834f62ed..46569b1b 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 @@ -2,8 +2,11 @@ package org.springframework.cloud.netflix.zuul.filters.route; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -12,6 +15,9 @@ import javax.ws.rs.core.MultivaluedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import com.netflix.client.ClientException; import com.netflix.client.http.HttpRequest.Verb; @@ -21,7 +27,7 @@ import com.netflix.niws.client.http.RestClient; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; -import com.netflix.zuul.util.HTTPRequestUtils; +import com.sun.jersey.core.util.MultivaluedMapImpl; public class RibbonRoutingFilter extends ZuulFilter { @@ -63,8 +69,8 @@ public class RibbonRoutingFilter extends ZuulFilter { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); - MultivaluedMap headers = helper.buildZuulRequestHeaders(request); - MultivaluedMap params = helper + MultiValueMap headers = helper.buildZuulRequestHeaders(request); + MultiValueMap params = helper .buildZuulRequestQueryParams(request); Verb verb = getVerb(request); InputStream requestEntity = getRequestBody(request); @@ -94,18 +100,18 @@ public class RibbonRoutingFilter extends ZuulFilter { } private HttpResponse forward(RestClient restClient, Verb verb, String uri, - MultivaluedMap headers, - MultivaluedMap params, InputStream requestEntity) - throws Exception { + MultiValueMap headers, MultiValueMap params, + InputStream requestEntity) throws Exception { Map info = helper.debug(verb.verb(), uri, headers, params, requestEntity); - RibbonCommand command = new RibbonCommand(restClient, verb, uri, headers, params, - requestEntity); + RibbonCommand command = new RibbonCommand(restClient, verb, uri, + convertHeaders(headers), convertHeaders(params), requestEntity); try { HttpResponse response = command.execute(); - helper.appendDebug(info, response.getStatus(), response.getHeaders()); + helper.appendDebug(info, response.getStatus(), + revertHeaders(response.getHeaders())); return response; } catch (HystrixRuntimeException e) { @@ -124,6 +130,24 @@ public class RibbonRoutingFilter extends ZuulFilter { } + private MultiValueMap revertHeaders( + Map> headers) { + MultiValueMap map = new LinkedMultiValueMap(); + for (Entry> entry : headers.entrySet()) { + map.put(entry.getKey(), new ArrayList(entry.getValue())); + } + return map; + } + + private MultivaluedMap convertHeaders( + MultiValueMap headers) { + MultivaluedMap map = new MultivaluedMapImpl(); + for (Entry> entry : headers.entrySet()) { + map.put(entry.getKey(), entry.getValue()); + } + return map; + } + private InputStream getRequestBody(HttpServletRequest request) { InputStream requestEntity = null; // ApacheHttpClient4Handler does not support body in delete requests @@ -168,7 +192,8 @@ public class RibbonRoutingFilter extends ZuulFilter { private void setResponse(HttpResponse resp) throws ClientException, IOException { helper.setResponse(resp.getStatus(), - !resp.hasEntity() ? null : resp.getInputStream(), resp.getHeaders()); + !resp.hasEntity() ? null : resp.getInputStream(), + revertHeaders(resp.getHeaders())); } } 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 990a2898..f734a23a 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 @@ -1,6 +1,5 @@ package org.springframework.cloud.netflix.zuul.filters.route; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; @@ -21,16 +20,13 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicReference; -import java.util.zip.GZIPInputStream; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.MultivaluedMap; -import org.apache.commons.io.IOUtils; import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; @@ -55,15 +51,16 @@ import org.apache.http.params.HttpParams; import org.apache.http.protocol.HttpContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import com.netflix.config.DynamicIntProperty; import com.netflix.config.DynamicPropertyFactory; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.constants.ZuulConstants; -import com.netflix.zuul.context.Debug; import com.netflix.zuul.context.RequestContext; -import com.netflix.zuul.util.HTTPRequestUtils; public class SimpleHostRoutingFilter extends ZuulFilter { @@ -215,8 +212,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter { public Object run() { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); - MultivaluedMap headers = helper.buildZuulRequestHeaders(request); - MultivaluedMap params = helper + MultiValueMap headers = helper.buildZuulRequestHeaders(request); + MultiValueMap params = helper .buildZuulRequestQueryParams(request); String verb = getVerb(request); InputStream requestEntity = getRequestBody(request); @@ -240,8 +237,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter { } private HttpResponse forward(HttpClient httpclient, String verb, String uri, - HttpServletRequest request, MultivaluedMap headers, - MultivaluedMap params, InputStream requestEntity) + HttpServletRequest request, MultiValueMap headers, + MultiValueMap params, InputStream requestEntity) throws Exception { Map info = helper @@ -289,8 +286,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter { } - private Map> revertHeaders(Header[] headers) { - Map> map = new LinkedHashMap>(); + private MultiValueMap revertHeaders(Header[] headers) { + MultiValueMap map = new LinkedMultiValueMap(); for (Header header : headers) { String name = header.getName(); if (!map.containsKey(name)) { @@ -301,7 +298,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter { return map; } - private Header[] convertHeaders(MultivaluedMap headers) { + private Header[] convertHeaders(MultiValueMap headers) { List
list = new ArrayList<>(); for (String name : headers.keySet()) { for (String value : headers.get(name)) {