KNOX-2103 - Make responseExcludeHeaders parameter in ConfigurableDispatch case insensitive (#192)
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
index 09c02da..c35af12 100644
--- 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
@@ -19,6 +19,8 @@
import org.apache.knox.gateway.config.Configure;
import org.apache.knox.gateway.config.Default;
+import org.apache.knox.gateway.util.StringUtils;
+
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URI;
@@ -63,7 +65,7 @@
}
private void populateSetCookieHeaderDirectiveExlusions(final Set<String> headerSet) {
- final Optional<String> setCookieHeader = headerSet.stream().filter(s -> s.startsWith(SET_COOKIE)).findFirst();
+ final Optional<String> setCookieHeader = headerSet.stream().filter(s -> StringUtils.startsWithIgnoreCase(s, SET_COOKIE)).findFirst();
if (setCookieHeader.isPresent()) {
final String[] setCookieHeaderParts = setCookieHeader.get().split(":");
responseExcludeSetCookieHeaderDirectives = setCookieHeaderParts.length > 1
@@ -75,7 +77,7 @@
}
private void populateHttpHeaderExlusionsOtherThanSetCookie(final Set<String> headerSet) {
- final Set<String> excludedHeadersOthenThanSetCookie = headerSet.stream().filter(s -> !s.startsWith(SET_COOKIE)).collect(Collectors.toSet());
+ final Set<String> excludedHeadersOthenThanSetCookie = headerSet.stream().filter(s -> !StringUtils.startsWithIgnoreCase(s, SET_COOKIE)).collect(Collectors.toSet());
if (!excludedHeadersOthenThanSetCookie.isEmpty()) {
this.responseExcludeHeaders = excludedHeadersOthenThanSetCookie;
}
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 3cf9816..10bfa2f 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
@@ -54,9 +54,9 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
-import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
import java.util.stream.Collectors;
public class DefaultDispatch extends AbstractGatewayDispatch {
@@ -315,10 +315,11 @@
}
public void copyResponseHeaderFields(HttpServletResponse outboundResponse, HttpResponse inboundResponse) {
- final Map<String, Set<String>> excludedHeaderDirectives = getOutboundResponseExcludeHeaders().stream().collect(Collectors.toMap(k -> k, v -> new HashSet<>(Arrays.asList(EXCLUDE_ALL))));
+ final TreeMap<String, Set<String>> excludedHeaderDirectives = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ getOutboundResponseExcludeHeaders().stream().forEach(excludeHeader -> excludedHeaderDirectives.put(excludeHeader, new HashSet<>(Arrays.asList(EXCLUDE_ALL))));
excludedHeaderDirectives.put(SET_COOKIE, getOutboundResponseExcludedSetCookieHeaderDirectives());
- for ( Header header : inboundResponse.getAllHeaders() ) {
+ for (Header header : inboundResponse.getAllHeaders()) {
final String responseHeaderValue = calculateResponseHeaderValue(header, excludedHeaderDirectives);
if (responseHeaderValue.isEmpty()) {
continue;
@@ -329,8 +330,8 @@
private String calculateResponseHeaderValue(Header headerToCheck, Map<String, Set<String>> excludedHeaderDirectives) {
final String headerNameToCheck = headerToCheck.getName();
- if (excludedHeaderDirectives != null && excludedHeaderDirectives.containsKey(headerNameToCheck.toUpperCase(Locale.ROOT))) {
- final Set<String> excludedHeaderValues = excludedHeaderDirectives.get(headerNameToCheck.toUpperCase(Locale.ROOT));
+ if (excludedHeaderDirectives != null && excludedHeaderDirectives.containsKey(headerNameToCheck)) {
+ final Set<String> excludedHeaderValues = excludedHeaderDirectives.get(headerNameToCheck);
if (!excludedHeaderValues.isEmpty()) {
if (excludedHeaderValues.stream().anyMatch(e -> e.equals(EXCLUDE_ALL))) {
return ""; // we should exclude all -> there should not be any value added with this header
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
index 07b98a8..191b561 100644
--- 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
@@ -238,12 +238,13 @@
@Test
public void testResponseExcludeHeadersConfig() {
ConfigurableDispatch dispatch = new ConfigurableDispatch();
- dispatch.setResponseExcludeHeaders(String.join(",", Collections.singletonList("TEST")));
+ dispatch.setResponseExcludeHeaders(String.join(",", Arrays.asList("test", "caseINSENSITIVEheader")));
Header[] headers = new Header[]{
new BasicHeader(SET_COOKIE, "abc"),
new BasicHeader(WWW_AUTHENTICATE, "negotiate"),
- new BasicHeader("TEST", "testValue")
+ new BasicHeader("TEST", "testValue"),
+ new BasicHeader("caseInsensitiveHeader", "caseInsensitiveHeaderValue")
};
HttpResponse inboundResponse = EasyMock.createNiceMock(HttpResponse.class);
diff --git a/gateway-util-common/src/main/java/org/apache/knox/gateway/util/StringUtils.java b/gateway-util-common/src/main/java/org/apache/knox/gateway/util/StringUtils.java
new file mode 100644
index 0000000..922f2cd
--- /dev/null
+++ b/gateway-util-common/src/main/java/org/apache/knox/gateway/util/StringUtils.java
@@ -0,0 +1,49 @@
+/*
+ * 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.util;
+
+public class StringUtils {
+
+ private StringUtils() {
+ };
+
+ /**
+ * @param str
+ * a String
+ * @param prefix
+ * a prefix
+ * @return true if {@code str} starts with {@code prefix}, ignoring case
+ * sensitivity
+ */
+ public static boolean startsWithIgnoreCase(String str, String prefix) {
+ return str.regionMatches(true, 0, prefix, 0, prefix.length());
+ }
+
+ /**
+ * @param str
+ * a String
+ * @param prefix
+ * a prefix
+ * @return true if {@code str} ends with {@code prefix}, ignoring case
+ * sensitivity
+ */
+ public static boolean endsWithIgnoreCase(String str, String suffix) {
+ int suffixLength = suffix.length();
+ return str.regionMatches(true, str.length() - suffixLength, suffix, 0, suffixLength);
+ }
+}
diff --git a/gateway-util-common/src/test/java/org/apache/knox/gateway/util/StringUtilsTest.java b/gateway-util-common/src/test/java/org/apache/knox/gateway/util/StringUtilsTest.java
new file mode 100644
index 0000000..89ebabe
--- /dev/null
+++ b/gateway-util-common/src/test/java/org/apache/knox/gateway/util/StringUtilsTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class StringUtilsTest {
+
+ @Test
+ public void testStartsWithIgnoreCase() throws Exception {
+ assertTrue(StringUtils.startsWithIgnoreCase("This Is A Sample Text", "this is a sample"));
+ assertTrue(StringUtils.startsWithIgnoreCase("THIS IS A SAMPLE TEXT", "This Is A Sample"));
+ assertTrue(StringUtils.startsWithIgnoreCase("this is a sample text", "THIS IS A SAMPLE"));
+ }
+
+ @Test
+ public void testEndsWithIgnoreCase() throws Exception {
+ assertTrue(StringUtils.endsWithIgnoreCase("This Is A Sample Text", "a sample text"));
+ assertTrue(StringUtils.endsWithIgnoreCase("THIS IS A SAMPLE TEXT", "a Sample Text"));
+ assertTrue(StringUtils.endsWithIgnoreCase("this is a sample text", "A SAMPLE TEXT"));
+ }
+}