Author: markt
Date: Wed Sep 3 17:37:51 2014
New Revision: 1622302
URL: http://svn.apache.org/r1622302
Log:
Correctly handle multiple accept-language headers rather than just using the
first header to determine the user's preferred Locale.
Modified:
tomcat/tc7.0.x/trunk/ (props changed)
tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java
tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TesterRequest.java
tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
Merged /tomcat/trunk:r1618112
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java?rev=1622302&r1=1622301&r2=1622302&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java Wed
Sep 3 17:37:51 2014
@@ -3226,26 +3226,33 @@ public class Request
localesParsed = true;
+ // Store the accumulated languages that have been requested in
+ // a local collection, sorted by the quality value (so we can
+ // add Locales in descending order). The values will be ArrayLists
+ // containing the corresponding Locales to be added
+ TreeMap<Double, ArrayList<Locale>> locales = new TreeMap<Double,
ArrayList<Locale>>();
+
Enumeration<String> values = getHeaders("accept-language");
while (values.hasMoreElements()) {
String value = values.nextElement();
- parseLocalesHeader(value);
+ parseLocalesHeader(value, locales);
}
+ // Process the quality values in highest->lowest order (due to
+ // negating the Double value when creating the key)
+ for (ArrayList<Locale> list : locales.values()) {
+ for (Locale locale : list) {
+ addLocale(locale);
+ }
+ }
}
/**
* Parse accept-language header value.
*/
- protected void parseLocalesHeader(String value) {
-
- // Store the accumulated languages that have been requested in
- // a local collection, sorted by the quality value (so we can
- // add Locales in descending order). The values will be ArrayLists
- // containing the corresponding Locales to be added
- TreeMap<Double, ArrayList<Locale>> locales = new TreeMap<Double,
ArrayList<Locale>>();
+ protected void parseLocalesHeader(String value, TreeMap<Double,
ArrayList<Locale>> locales) {
// Preprocess the value to remove all whitespace
int white = value.indexOf(' ');
@@ -3340,17 +3347,7 @@ public class Request
locales.put(key, values);
}
values.add(locale);
-
- }
-
- // Process the quality values in highest->lowest order (due to
- // negating the Double value when creating the key)
- for (ArrayList<Locale> list : locales.values()) {
- for (Locale locale : list) {
- addLocale(locale);
- }
}
-
}
Modified:
tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java?rev=1622302&r1=1622301&r2=1622302&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
(original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
Wed Sep 3 17:37:51 2014
@@ -28,6 +28,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
+import java.util.Locale;
import java.util.TreeMap;
import javax.servlet.ServletException;
@@ -40,6 +41,7 @@ import static org.junit.Assert.assertNot
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import org.junit.Assert;
import org.junit.Test;
import org.apache.catalina.Context;
@@ -660,7 +662,7 @@ public class TestRequest extends TomcatB
writer.append("Content-Disposition: form-data; name=\"part\"\r\n");
writer.append("Content-Type: text/plain; charset=UTF-8\r\n");
writer.append("\r\n");
- writer.append("äö").append("\r\n");
+ writer.append("��").append("\r\n");
writer.flush();
writer.append("\r\n");
@@ -687,7 +689,7 @@ public class TestRequest extends TomcatB
while ((line = reader.readLine()) != null) {
response.add(line);
}
- assertTrue(response.contains("Part äö"));
+ assertTrue(response.contains("Part ��"));
} finally {
if (reader != null) {
reader.close();
@@ -807,4 +809,35 @@ public class TestRequest extends TomcatB
resp.getWriter().print(req.getContextPath());
}
}
+
+ @Test
+ public void getLocaleMultipleHeaders01() throws Exception {
+ TesterRequest req = new TesterRequest();
+
+ req.addHeader("accept-language", "en;q=0.5");
+ req.addHeader("accept-language", "en-gb");
+
+ Locale actual = req.getLocale();
+ Locale expected = Locale.forLanguageTag("en-gb");
+
+ Assert.assertEquals(expected, actual);
+ }
+
+ /*
+ * Reverse header order of getLocaleMultipleHeaders01() and make sure the
+ * result is the same.
+ */
+ @Test
+ public void getLocaleMultipleHeaders02() throws Exception {
+ TesterRequest req = new TesterRequest();
+
+ req.addHeader("accept-language", "en-gb");
+ req.addHeader("accept-language", "en;q=0.5");
+
+ Locale actual = req.getLocale();
+ Locale expected = Locale.forLanguageTag("en-gb");
+
+ Assert.assertEquals(expected, actual);
+ }
+
}
Modified:
tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TesterRequest.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TesterRequest.java?rev=1622302&r1=1622301&r2=1622302&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TesterRequest.java
(original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/connector/TesterRequest.java
Wed Sep 3 17:37:51 2014
@@ -16,6 +16,13 @@
*/
package org.apache.catalina.connector;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
public class TesterRequest extends Request {
@Override
public String getScheme() {
@@ -45,4 +52,31 @@ public class TesterRequest extends Reque
public String getMethod() {
return method;
}
+
+ private final Map<String,List<String>> headers = new HashMap<String,
List<String>>();
+ protected void addHeader(String name, String value) {
+ List<String> values = headers.get(name);
+ if (values == null) {
+ values = new ArrayList<String>();
+ headers.put(name, values);
+ }
+ values.add(value);
+ }
+ @Override
+ public String getHeader(String name) {
+ List<String> values = headers.get(name);
+ if (values == null || values.size() == 0) {
+ return null;
+ }
+ return values.get(0);
+ }
+ @Override
+ public Enumeration<String> getHeaders(String name) {
+ return Collections.enumeration(headers.get(name));
+ }
+
+ @Override
+ public Enumeration<String> getHeaderNames() {
+ return Collections.enumeration(headers.keySet());
+ }
}
Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1622302&r1=1622301&r2=1622302&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Sep 3 17:37:51 2014
@@ -136,6 +136,11 @@
Fix a potential resource leak when reading MANIFEST.MF file for
extension dependencies reported by Coverity Scan. (violetagg)
</fix>
+ <fix>
+ Correctly handle multiple <code>accept-language</code> headers rather
+ than just using the first header to determine the user's preferred
+ Locale. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]