You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by kr...@apache.org on 2019/01/24 15:52:34 UTC
[knox] branch master updated: KNOX-1559 - Create Dispatch
implementation that is configurable via service.xml file
This is an automated email from the ASF dual-hosted git repository.
krisden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new cd29c4b KNOX-1559 - Create Dispatch implementation that is configurable via service.xml file
cd29c4b is described below
commit cd29c4b8171d2610cc46113efc68ed319b989a3a
Author: Kevin Risden <kr...@apache.org>
AuthorDate: Mon Nov 19 16:33:27 2018 -0500
KNOX-1559 - Create Dispatch implementation that is configurable via service.xml file
Signed-off-by: Kevin Risden <kr...@apache.org>
---
.../gateway/dispatch/AbstractGatewayDispatch.java | 12 +-
.../gateway/dispatch/ConfigurableDispatch.java | 104 +++++++++
.../knox/gateway/dispatch/DefaultDispatch.java | 44 ++--
.../gateway/dispatch/PassAllHeadersDispatch.java | 11 +-
.../dispatch/PassAllHeadersNoEncodingDispatch.java | 42 ++--
.../gateway/dispatch/ConfigurableDispatchTest.java | 258 +++++++++++++++++++++
6 files changed, 406 insertions(+), 65 deletions(-)
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
index a973dcc..0214255 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
@@ -29,20 +29,14 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
public abstract class AbstractGatewayDispatch implements Dispatch {
-
- private static final Set<String> REQUEST_EXCLUDE_HEADERS = new HashSet<>();
-
- static {
- REQUEST_EXCLUDE_HEADERS.add("Host");
- REQUEST_EXCLUDE_HEADERS.add("Authorization");
- REQUEST_EXCLUDE_HEADERS.add("Content-Length");
- REQUEST_EXCLUDE_HEADERS.add("Transfer-Encoding");
- }
+ private static final Set<String> REQUEST_EXCLUDE_HEADERS = new HashSet<>(Arrays.asList(
+ "Host", "Authorization", "Content-Length", "Transfer-Encoding"));
protected HttpClient client;
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/ConfigurableDispatch.java b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/ConfigurableDispatch.java
new file mode 100644
index 0000000..1611307
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/ConfigurableDispatch.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.dispatch;
+
+import org.apache.knox.gateway.config.Configure;
+import org.apache.knox.gateway.config.Default;
+import javax.servlet.http.HttpServletRequest;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Extends DefaultDispatch to:
+ * make request/response exclude headers configurable
+ * make url encoding configurable
+ */
+public class ConfigurableDispatch extends DefaultDispatch {
+ private Set<String> requestExcludeHeaders = super.getOutboundRequestExcludeHeaders();
+ private Set<String> responseExcludeHeaders = super.getOutboundResponseExcludeHeaders();
+ private Boolean removeUrlEncoding = false;
+
+ private Set<String> handleCommaSeparatedHeaders(String headers) {
+ if(headers != null) {
+ return new HashSet<>(Arrays.asList(headers.split(",")));
+ }
+ return Collections.emptySet();
+ }
+
+ @Configure
+ protected void setRequestExcludeHeaders(@Default(" ") String headers) {
+ if(!" ".equals(headers)) {
+ this.requestExcludeHeaders = handleCommaSeparatedHeaders(headers);
+ }
+ }
+
+ @Configure
+ protected void setResponseExcludeHeaders(@Default(" ") String headers) {
+ if(!" ".equals(headers)) {
+ this.responseExcludeHeaders = handleCommaSeparatedHeaders(headers);
+ }
+ }
+
+ @Configure
+ protected void setRemoveUrlEncoding(@Default("false") String removeUrlEncoding) {
+ this.removeUrlEncoding = Boolean.parseBoolean(removeUrlEncoding);
+ }
+
+ @Override
+ public Set<String> getOutboundResponseExcludeHeaders() {
+ return responseExcludeHeaders;
+ }
+
+ @Override
+ public Set<String> getOutboundRequestExcludeHeaders() {
+ return requestExcludeHeaders;
+ }
+
+ public boolean getRemoveUrlEncoding() {
+ return removeUrlEncoding;
+ }
+
+ @Override
+ public URI getDispatchUrl(HttpServletRequest request) {
+ if (getRemoveUrlEncoding()) {
+ String base = request.getRequestURI();
+ StringBuffer str = new StringBuffer();
+ str.append(base);
+ String query = request.getQueryString();
+ if (query != null) {
+ try {
+ query = URLDecoder.decode(query, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ // log
+ }
+ str.append('?');
+ str.append(query);
+ }
+ encodeUnwiseCharacters(str);
+ return URI.create(str.toString());
+ }
+
+ return super.getDispatchUrl(request);
+ }
+}
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
index 8b899b9..5f0b3e4 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
@@ -50,6 +50,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
@@ -64,20 +65,12 @@ public class DefaultDispatch extends AbstractGatewayDispatch {
protected static final Auditor auditor = AuditServiceFactory.getAuditService().getAuditor(AuditConstants.DEFAULT_AUDITOR_NAME,
AuditConstants.KNOX_SERVICE_NAME, AuditConstants.KNOX_COMPONENT_NAME);
- private Set<String> outboundResponseExcludeHeaders;
+ private Set<String> outboundResponseExcludeHeaders = new HashSet<>(Arrays.asList(SET_COOKIE, WWW_AUTHENTICATE));
//Buffer size in bytes
private int replayBufferSize = -1;
@Override
- public void init() {
- super.init();
- outboundResponseExcludeHeaders = new HashSet<>();
- outboundResponseExcludeHeaders.add(SET_COOKIE);
- outboundResponseExcludeHeaders.add(WWW_AUTHENTICATE);
- }
-
- @Override
public void destroy() {
}
@@ -151,20 +144,7 @@ public class DefaultDispatch extends AbstractGatewayDispatch {
protected void writeOutboundResponse(HttpUriRequest outboundRequest, HttpServletRequest inboundRequest, HttpServletResponse outboundResponse, HttpResponse inboundResponse) throws IOException {
// Copy the client respond header to the server respond.
outboundResponse.setStatus(inboundResponse.getStatusLine().getStatusCode());
- Header[] headers = inboundResponse.getAllHeaders();
- Set<String> excludeHeaders = getOutboundResponseExcludeHeaders();
- boolean hasExcludeHeaders = false;
- if ((excludeHeaders != null) && !(excludeHeaders.isEmpty())) {
- hasExcludeHeaders = true;
- }
- for ( Header header : headers ) {
- String name = header.getName();
- if (hasExcludeHeaders && excludeHeaders.contains(name.toUpperCase(Locale.ROOT))) {
- continue;
- }
- String value = header.getValue();
- outboundResponse.addHeader(name, value);
- }
+ copyResponseHeaderFields(outboundResponse, inboundResponse);
HttpEntity entity = inboundResponse.getEntity();
if( entity != null ) {
@@ -318,8 +298,24 @@ public class DefaultDispatch extends AbstractGatewayDispatch {
executeRequest(method, request, response);
}
+ public void copyResponseHeaderFields(HttpServletResponse outboundResponse, HttpResponse inboundResponse) {
+ Header[] headers = inboundResponse.getAllHeaders();
+ Set<String> excludeHeaders = getOutboundResponseExcludeHeaders();
+ boolean hasExcludeHeaders = false;
+ if ((excludeHeaders != null) && !(excludeHeaders.isEmpty())) {
+ hasExcludeHeaders = true;
+ }
+ for ( Header header : headers ) {
+ String name = header.getName();
+ if (hasExcludeHeaders && excludeHeaders.contains(name.toUpperCase(Locale.ROOT))) {
+ continue;
+ }
+ String value = header.getValue();
+ outboundResponse.addHeader(name, value);
+ }
+ }
+
public Set<String> getOutboundResponseExcludeHeaders() {
return outboundResponseExcludeHeaders;
}
-
}
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersDispatch.java b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersDispatch.java
index 6267047..2af8dc9 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersDispatch.java
@@ -21,7 +21,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
-public class PassAllHeadersDispatch extends DefaultDispatch {
+public class PassAllHeadersDispatch extends ConfigurableDispatch {
private static final Set<String> REQUEST_EXCLUDE_HEADERS = new HashSet<>();
@@ -30,8 +30,13 @@ public class PassAllHeadersDispatch extends DefaultDispatch {
}
@Override
- public void init() {
- super.init();
+ protected void setResponseExcludeHeaders(String headers) {
+ super.setResponseExcludeHeaders(String.join(",", REQUEST_EXCLUDE_HEADERS));
+ }
+
+ @Override
+ protected void setRequestExcludeHeaders(String headers) {
+ super.setRequestExcludeHeaders("");
}
@Override
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersNoEncodingDispatch.java b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersNoEncodingDispatch.java
index e947057..6177e0f 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersNoEncodingDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/PassAllHeadersNoEncodingDispatch.java
@@ -17,35 +17,19 @@
*/
package org.apache.knox.gateway.dispatch;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-
-import javax.servlet.http.HttpServletRequest;
-
- /**
- * This is a specialized PassAllHeadersDispatch dispatch that decodes the URL before
- * dispatch. Ambari Views do not work with the query string percent encoded. Other
- * UIs may require this at some point as well.
- */
+/**
+ * This is a specialized PassAllHeadersDispatch dispatch that decodes the URL before
+ * dispatch. Ambari Views do not work with the query string percent encoded. Other
+ * UIs may require this at some point as well.
+ */
public class PassAllHeadersNoEncodingDispatch extends PassAllHeadersDispatch {
@Override
- public URI getDispatchUrl(HttpServletRequest request) {
- String base = request.getRequestURI();
- StringBuffer str = new StringBuffer();
- str.append( base );
- String query = request.getQueryString();
- if (query != null) {
- try {
- query = URLDecoder.decode(query, StandardCharsets.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- // log
- }
- str.append( '?' );
- str.append( query );
- }
- encodeUnwiseCharacters(str);
- return URI.create( str.toString() );
+ protected void setRemoveUrlEncoding(String removeUrlEncoding) {
+ super.setRemoveUrlEncoding(Boolean.TRUE.toString());
+ }
+
+ @Override
+ public boolean getRemoveUrlEncoding() {
+ return Boolean.TRUE;
}
-}
+}
\ No newline at end of file
diff --git a/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/ConfigurableDispatchTest.java b/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/ConfigurableDispatchTest.java
new file mode 100644
index 0000000..3e6d2af
--- /dev/null
+++ b/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/ConfigurableDispatchTest.java
@@ -0,0 +1,258 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.dispatch;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.message.BasicHeader;
+import org.apache.knox.test.TestUtils;
+import org.apache.knox.test.mock.MockHttpServletResponse;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.knox.gateway.dispatch.DefaultDispatch.SET_COOKIE;
+import static org.apache.knox.gateway.dispatch.DefaultDispatch.WWW_AUTHENTICATE;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ConfigurableDispatchTest {
+ @Test( timeout = TestUtils.SHORT_TIMEOUT )
+ public void testGetDispatchUrl() {
+ HttpServletRequest request;
+ String path;
+ String query;
+ URI uri;
+
+ ConfigurableDispatch dispatch = new ConfigurableDispatch();
+
+ path = "http://test-host:42/test-path";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( null ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test-path" ) );
+
+ path = "http://test-host:42/test,path";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( null ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test,path" ) );
+
+ path = "http://test-host:42/test%2Cpath";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( null ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test%2Cpath" ) );
+
+ path = "http://test-host:42/test%2Cpath";
+ query = "test%26name=test%3Dvalue";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( query ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test%2Cpath?test%26name=test%3Dvalue" ) );
+ }
+
+ @Test( timeout = TestUtils.SHORT_TIMEOUT )
+ public void testGetDispatchUrlNoUrlEncoding() {
+ HttpServletRequest request;
+ String path;
+ String query;
+ URI uri;
+
+ ConfigurableDispatch dispatch = new ConfigurableDispatch();
+ dispatch.setRemoveUrlEncoding(Boolean.TRUE.toString());
+
+ path = "http://test-host:42/test-path";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( null ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test-path" ) );
+
+ path = "http://test-host:42/test,path";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( null ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test,path" ) );
+
+ // encoding in the patch remains
+ path = "http://test-host:42/test%2Cpath";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( null ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test%2Cpath" ) );
+
+ // encoding in query string is removed
+ path = "http://test-host:42/test%2Cpath";
+ query = "test%26name=test%3Dvalue";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( query ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:42/test%2Cpath?test&name=test=value" ) );
+
+ // double quotes removed
+ path = "https://test-host:42/api/v1/views/TEZ/versions/0.7.0.2.6.2.0-205/instances/TEZ_CLUSTER_INSTANCE/resources/atsproxy/ws/v1/timeline/TEZ_DAG_ID";
+ query = "limit=9007199254740991&primaryFilter=applicationId:%22application_1518808140659_0007%22&_=1519053586839";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( query ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "https://test-host:42/api/v1/views/TEZ/versions/0.7.0.2.6.2.0-205/instances/TEZ_CLUSTER_INSTANCE/resources/atsproxy/ws/v1/timeline/TEZ_DAG_ID?limit=9007199254740991&primaryFilter=applicationId:%22application_1518808140659_0007%22&_=1519053586839" ) );
+
+ // encode < and > sign
+ path = "http://test-host:8080/api/v1/clusters/mmolnar-knox2/configurations/service_config_versions";
+ query = "group_id%3E0&fields=*&_=1541527314780";
+ request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.expect( request.getRequestURI() ).andReturn( path ).anyTimes();
+ EasyMock.expect( request.getRequestURL() ).andReturn( new StringBuffer( path ) ).anyTimes();
+ EasyMock.expect( request.getQueryString() ).andReturn( query ).anyTimes();
+ EasyMock.replay( request );
+ uri = dispatch.getDispatchUrl( request );
+ assertThat( uri.toASCIIString(), is( "http://test-host:8080/api/v1/clusters/mmolnar-knox2/configurations/service_config_versions?group_id%3E0&fields=*&_=1541527314780" ) );
+ }
+
+ @Test( timeout = TestUtils.SHORT_TIMEOUT )
+ public void testRequestExcludeHeadersDefault() {
+ ConfigurableDispatch dispatch = new ConfigurableDispatch();
+
+ Map<String, String> headers = new HashMap<>();
+ headers.put(HttpHeaders.AUTHORIZATION, "Basic ...");
+ headers.put(HttpHeaders.ACCEPT, "abc");
+ headers.put("TEST", "test");
+
+ HttpServletRequest inboundRequest = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(inboundRequest.getHeaderNames()).andReturn(Collections.enumeration(headers.keySet())).anyTimes();
+ Capture<String> capturedArgument = Capture.newInstance();
+ EasyMock.expect(inboundRequest.getHeader(EasyMock.capture(capturedArgument)))
+ .andAnswer(() -> headers.get(capturedArgument.getValue())).anyTimes();
+ EasyMock.replay(inboundRequest);
+
+ HttpUriRequest outboundRequest = new HttpGet();
+ dispatch.copyRequestHeaderFields(outboundRequest, inboundRequest);
+
+ Header[] outboundRequestHeaders = outboundRequest.getAllHeaders();
+ assertThat(outboundRequestHeaders.length, is(2));
+ assertThat(outboundRequestHeaders[0].getName(), is(HttpHeaders.ACCEPT));
+ assertThat(outboundRequestHeaders[1].getName(), is("TEST"));
+ }
+
+ @Test( timeout = TestUtils.SHORT_TIMEOUT )
+ public void testRequestExcludeHeadersConfig() {
+ ConfigurableDispatch dispatch = new ConfigurableDispatch();
+ dispatch.setRequestExcludeHeaders(String.join(",", Arrays.asList(HttpHeaders.ACCEPT, "TEST")));
+
+ Map<String, String> headers = new HashMap<>();
+ headers.put(HttpHeaders.AUTHORIZATION, "Basic ...");
+ headers.put(HttpHeaders.ACCEPT, "abc");
+ headers.put("TEST", "test");
+
+ HttpServletRequest inboundRequest = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(inboundRequest.getHeaderNames()).andReturn(Collections.enumeration(headers.keySet())).anyTimes();
+ Capture<String> capturedArgument = Capture.newInstance();
+ EasyMock.expect(inboundRequest.getHeader(EasyMock.capture(capturedArgument)))
+ .andAnswer(() -> headers.get(capturedArgument.getValue())).anyTimes();
+ EasyMock.replay(inboundRequest);
+
+ HttpUriRequest outboundRequest = new HttpGet();
+ dispatch.copyRequestHeaderFields(outboundRequest, inboundRequest);
+
+ Header[] outboundRequestHeaders = outboundRequest.getAllHeaders();
+ assertThat(outboundRequestHeaders.length, is(1));
+ assertThat(outboundRequestHeaders[0].getName(), is(HttpHeaders.AUTHORIZATION));
+ }
+
+ @Test( timeout = TestUtils.SHORT_TIMEOUT )
+ public void testResponseExcludeHeadersDefault() {
+ ConfigurableDispatch dispatch = new ConfigurableDispatch();
+
+ Header[] headers = new Header[]{
+ new BasicHeader(SET_COOKIE, "abc"),
+ new BasicHeader(WWW_AUTHENTICATE, "negotiate"),
+ new BasicHeader("TEST", "testValue")
+ };
+
+ HttpResponse inboundResponse = EasyMock.createNiceMock(HttpResponse.class);
+ EasyMock.expect(inboundResponse.getAllHeaders()).andReturn(headers).anyTimes();
+ EasyMock.replay(inboundResponse);
+
+ HttpServletResponse outboundResponse = new MockHttpServletResponse();
+ dispatch.copyResponseHeaderFields(outboundResponse, inboundResponse);
+
+ assertThat(outboundResponse.getHeaderNames().size(), is(1));
+ assertThat(outboundResponse.getHeader("TEST"), is("testValue"));
+ }
+
+ @Test( timeout = TestUtils.SHORT_TIMEOUT )
+ public void testResponseExcludeHeadersConfig() {
+ ConfigurableDispatch dispatch = new ConfigurableDispatch();
+ dispatch.setResponseExcludeHeaders(String.join(",", Collections.singletonList("TEST")));
+
+ Header[] headers = new Header[]{
+ new BasicHeader(SET_COOKIE, "abc"),
+ new BasicHeader(WWW_AUTHENTICATE, "negotiate"),
+ new BasicHeader("TEST", "testValue")
+ };
+
+ HttpResponse inboundResponse = EasyMock.createNiceMock(HttpResponse.class);
+ EasyMock.expect(inboundResponse.getAllHeaders()).andReturn(headers).anyTimes();
+ EasyMock.replay(inboundResponse);
+
+ HttpServletResponse outboundResponse = new MockHttpServletResponse();
+ dispatch.copyResponseHeaderFields(outboundResponse, inboundResponse);
+
+ assertThat(outboundResponse.getHeaderNames().size(), is(2));
+ assertThat(outboundResponse.getHeader(SET_COOKIE), is("abc"));
+ assertThat(outboundResponse.getHeader(WWW_AUTHENTICATE), is("negotiate"));
+ }
+}