You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2018/07/06 15:26:30 UTC
svn commit: r1835261 - in /tomcat/trunk:
java/org/apache/tomcat/util/http/ResponseUtil.java
test/org/apache/tomcat/util/http/TestResponseUtil.java
Author: markt
Date: Fri Jul 6 15:26:30 2018
New Revision: 1835261
URL: http://svn.apache.org/viewvc?rev=1835261&view=rev
Log:
Add a utility method (and associated test cases) that adds updates / creates a Vary header with a given field name. Multiple headers will be collapsed and invalid values removed.
Added:
tomcat/trunk/java/org/apache/tomcat/util/http/ResponseUtil.java (with props)
tomcat/trunk/test/org/apache/tomcat/util/http/TestResponseUtil.java (with props)
Added: tomcat/trunk/java/org/apache/tomcat/util/http/ResponseUtil.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/ResponseUtil.java?rev=1835261&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/ResponseUtil.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/ResponseUtil.java Fri Jul 6 15:26:30 2018
@@ -0,0 +1,93 @@
+/*
+ * 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.tomcat.util.http;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tomcat.util.http.parser.Vary;
+
+public class ResponseUtil {
+
+ private static final String VARY_HEADER = "vary";
+ private static final String VARY_ALL = "*";
+
+ private ResponseUtil() {
+ // Utility class. Hide default constructor.
+ }
+
+
+ public static void addVaryFieldName(HttpServletResponse response, String name) {
+ Collection<String> varyHeaders = response.getHeaders(VARY_HEADER);
+
+ // Short-cut if only * has been set
+ if (varyHeaders.size() == 1 && varyHeaders.iterator().next().trim().equals(VARY_ALL)) {
+ // No need to add an additional field
+ return;
+ }
+
+ // Short-cut if no headers have been set
+ if (varyHeaders.size() == 0) {
+ response.addHeader(VARY_HEADER, name);
+ return;
+ }
+
+ // Short-cut if "*" is added
+ if (VARY_ALL.equals(name.trim())) {
+ response.setHeader(VARY_HEADER, VARY_ALL);
+ return;
+ }
+
+ // May be dealing with an application set header, or multiple headers.
+ // Header names overlap so can't use String.contains(). Have to parse
+ // the existing values, check if the new value is already present and
+ // then add it if not. The good news is field names are tokens which
+ // makes parsing simpler.
+ Set<String> fieldNames = new HashSet<>();
+
+ for (String varyHeader : varyHeaders) {
+ StringReader input = new StringReader(varyHeader);
+ try {
+ Vary.parseVary(input, fieldNames);
+ } catch (IOException ioe) {
+ // Should never happen
+ }
+ }
+
+ if (fieldNames.contains(VARY_ALL)) {
+ // '*' has been added without removing other values. Optimise.
+ response.setHeader(VARY_HEADER, VARY_ALL);
+ return;
+ }
+
+ // Build single header to replace current multiple headers
+ // Replace existing header(s) to ensure any invalid values are removed
+ fieldNames.add(name);
+ StringBuilder varyHeader = new StringBuilder();
+ varyHeader.append(name);
+ for (String fieldName : fieldNames) {
+ varyHeader.append(',');
+ varyHeader.append(fieldName);
+ }
+ response.setHeader(VARY_HEADER, varyHeader.toString());
+ }
+}
Propchange: tomcat/trunk/java/org/apache/tomcat/util/http/ResponseUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/test/org/apache/tomcat/util/http/TestResponseUtil.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/TestResponseUtil.java?rev=1835261&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/http/TestResponseUtil.java (added)
+++ tomcat/trunk/test/org/apache/tomcat/util/http/TestResponseUtil.java Fri Jul 6 15:26:30 2018
@@ -0,0 +1,182 @@
+/*
+ * 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.tomcat.util.http;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.tomcat.unittest.TesterResponse;
+
+public class TestResponseUtil {
+
+ @Test
+ public void testAddValidWithAll() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "host");
+ Set<String> expected = new HashSet<>();
+ expected.add("*");
+ doTestAddVaryFieldName(response, "*", expected);
+ }
+
+
+ @Test
+ public void testAddAllWithAll() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "*");
+ Set<String> expected = new HashSet<>();
+ expected.add("*");
+ doTestAddVaryFieldName(response, "*", expected);
+ }
+
+
+ @Test
+ public void testAddAllWithNone() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ Set<String> expected = new HashSet<>();
+ expected.add("*");
+ doTestAddVaryFieldName(response, "*", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithValidSingleHeader() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "foo, bar");
+ Set<String> expected = new HashSet<>();
+ expected.add("bar");
+ expected.add("foo");
+ expected.add("too");
+ doTestAddVaryFieldName(response, "too", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithValidSingleHeaderIncludingAll() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "foo, *");
+ Set<String> expected = new HashSet<>();
+ expected.add("*");
+ doTestAddVaryFieldName(response, "too", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithValidSingleHeaderAlreadyPresent() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "foo, bar");
+ Set<String> expected = new HashSet<>();
+ expected.add("bar");
+ expected.add("foo");
+ doTestAddVaryFieldName(response, "foo", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithValidHeaders() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "foo");
+ response.addHeader("vary", "bar");
+ Set<String> expected = new HashSet<>();
+ expected.add("bar");
+ expected.add("foo");
+ expected.add("too");
+ doTestAddVaryFieldName(response, "too", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithValidHeadersIncludingAll() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "foo");
+ response.addHeader("vary", "*");
+ Set<String> expected = new HashSet<>();
+ expected.add("*");
+ doTestAddVaryFieldName(response, "too", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithValidHeadersAlreadyPresent() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "foo");
+ response.addHeader("vary", "bar");
+ Set<String> expected = new HashSet<>();
+ expected.add("bar");
+ expected.add("foo");
+ doTestAddVaryFieldName(response, "foo", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithPartiallyValidSingleHeader() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "{{{, bar");
+ Set<String> expected = new HashSet<>();
+ expected.add("bar");
+ expected.add("too");
+ doTestAddVaryFieldName(response, "too", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithPartiallyValidSingleHeaderIncludingAll() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "{{{, *");
+ Set<String> expected = new HashSet<>();
+ expected.add("*");
+ doTestAddVaryFieldName(response, "too", expected);
+ }
+
+
+ @Test
+ public void testAddValidWithPartiallyValidSingleHeaderAlreadyPresent() {
+ TesterResponse response = new TesterResponse();
+ response.getCoyoteResponse();
+ response.addHeader("vary", "{{{, bar");
+ Set<String> expected = new HashSet<>();
+ expected.add("bar");
+ doTestAddVaryFieldName(response, "bar", expected);
+ }
+
+
+ private void doTestAddVaryFieldName(TesterResponse response, String fieldName,
+ Set<String> expected) {
+ ResponseUtil.addVaryFieldName(response, fieldName);
+ // There will now only be one Vary header
+ String resultHeader = response.getHeader("vary");
+ Set<String> result = new HashSet<>();
+ // Deliberately do not use Vary.parseVary as it will skip invalid values.
+ for (String value : resultHeader.split(",")) {
+ result.add(value.trim());
+ }
+ Assert.assertEquals(expected, result);
+ }
+}
Propchange: tomcat/trunk/test/org/apache/tomcat/util/http/TestResponseUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org