Author: markt Date: Mon Jun 19 18:34:02 2017 New Revision: 1799253 URL: http://svn.apache.org/viewvc?rev=1799253&view=rev Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=61197 Ensure that the charset name used in the Content-Type header has exactly the same form as that provided by the application. This reverts a behavioural change in 9.0.0.M21 that caused problems for some clients.
Added: tomcat/trunk/test/org/apache/coyote/TestResponse.java (with props) Modified: tomcat/trunk/java/org/apache/catalina/connector/Response.java tomcat/trunk/java/org/apache/coyote/Response.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/catalina/connector/Response.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Response.java?rev=1799253&r1=1799252&r2=1799253&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/Response.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/Response.java Mon Jun 19 18:34:02 2017 @@ -56,7 +56,6 @@ import org.apache.catalina.util.SessionC import org.apache.coyote.ActionCode; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.util.buf.B2CConverter; import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.buf.UEncoder; import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet; @@ -553,9 +552,9 @@ public class Response implements HttpSer */ @Override public String getCharacterEncoding() { - Charset charset = getCoyoteResponse().getCharset(); + String charset = getCoyoteResponse().getCharsetName(); if (charset != null) { - return charset.name(); + return charset; } Context context = getContext(); @@ -804,7 +803,7 @@ public class Response implements HttpSer // Ignore charset if getWriter() has already been called if (!usingWriter) { try { - getCoyoteResponse().setCharset(B2CConverter.getCharset(m[1])); + getCoyoteResponse().setCharset(m[1]); } catch (UnsupportedEncodingException e) { log.warn(sm.getString("coyoteResponse.encoding.invalid", m[1]), e); } @@ -841,7 +840,7 @@ public class Response implements HttpSer } try { - getCoyoteResponse().setCharset(B2CConverter.getCharset(charset)); + getCoyoteResponse().setCharset(charset); } catch (UnsupportedEncodingException e) { log.warn(sm.getString("coyoteResponse.encoding.invalid", charset), e); return; @@ -883,7 +882,7 @@ public class Response implements HttpSer String charset = getContext().getCharset(locale); if (charset != null) { try { - getCoyoteResponse().setCharset(B2CConverter.getCharset(charset)); + getCoyoteResponse().setCharset(charset); } catch (UnsupportedEncodingException e) { log.warn(sm.getString("coyoteResponse.encoding.invalid", charset), e); } Modified: tomcat/trunk/java/org/apache/coyote/Response.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Response.java?rev=1799253&r1=1799252&r2=1799253&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/Response.java (original) +++ tomcat/trunk/java/org/apache/coyote/Response.java Mon Jun 19 18:34:02 2017 @@ -112,6 +112,10 @@ public final class Response { String contentType = null; String contentLanguage = null; Charset charset = null; + // Retain the original name used to set the charset so exactly that name is + // used in the ContentType header. Some (arguably non-specification + // compliant) user agents are very particular + String charsetName = null; long contentLength = -1; private Locale locale = DEFAULT_LOCALE; @@ -415,17 +419,21 @@ public final class Response { * Overrides the character encoding used in the body of the response. This * method must be called prior to writing output using getWriter(). * - * @param charset The character encoding. + * @param charsetName The name of character encoding. + * + * @throws UnsupportedEncodingException If the specified name is not + * recognised */ - public void setCharset(Charset charset) { + public void setCharset(String charsetName) throws UnsupportedEncodingException { if (isCommitted()) { return; } - if (charset == null) { + if (charsetName == null) { return; } - this.charset = charset; + this.charset = B2CConverter.getCharset(charsetName); + this.charsetName = charsetName; } @@ -434,6 +442,11 @@ public final class Response { } + public String getCharsetName() { + return charsetName; + } + + /** * Sets the content type. * @@ -489,7 +502,7 @@ public final class Response { if (ret != null && charset != null) { - ret = ret + ";charset=" + charset.name(); + ret = ret + ";charset=" + charsetName; } return ret; @@ -534,6 +547,7 @@ public final class Response { contentLanguage = null; locale = DEFAULT_LOCALE; charset = null; + charsetName = null; contentLength = -1; status = 200; message = null; Added: tomcat/trunk/test/org/apache/coyote/TestResponse.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/TestResponse.java?rev=1799253&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/coyote/TestResponse.java (added) +++ tomcat/trunk/test/org/apache/coyote/TestResponse.java Mon Jun 19 18:34:02 2017 @@ -0,0 +1,81 @@ +/* + * 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.coyote; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.catalina.Context; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.tomcat.util.buf.ByteChunk; + +public class TestResponse extends TomcatBaseTest { + + /* + * https://bz.apache.org/bugzilla/show_bug.cgi?id=61197 + */ + @Test + public void testUserCharsetIsRetained() throws Exception { + Tomcat tomcat = getTomcatInstance(); + + // No file system docBase required + Context ctx = tomcat.addContext("", null); + + // Add servlet + Tomcat.addServlet(ctx, "CharsetServlet", new CharsetServlet()); + ctx.addServletMappingDecoded("/*", "CharsetServlet"); + + tomcat.start(); + + ByteChunk responseBody = new ByteChunk(); + Map<String,List<String>> responseHeaders = new HashMap<>(); + int rc = getUrl("http://localhost:" + getPort() + "/test?charset=uTf-8", responseBody, + responseHeaders); + + Assert.assertEquals(HttpServletResponse.SC_OK, rc); + Assert.assertTrue(responseHeaders.containsKey("Content-Type")); + List<String> contentType = responseHeaders.get("Content-Type"); + Assert.assertEquals(1, contentType.size()); + Assert.assertEquals("text/plain;charset=uTf-8", contentType.get(0)); + } + + + private static class CharsetServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text/plain"); + resp.setCharacterEncoding(req.getParameter("charset")); + + resp.getWriter().print("OK"); + } + } +} Propchange: tomcat/trunk/test/org/apache/coyote/TestResponse.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1799253&r1=1799252&r2=1799253&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon Jun 19 18:34:02 2017 @@ -125,6 +125,12 @@ <code>getRequestURI()</code> for the dispatched request matches that of the original request. (markt) </fix> + <fix> + <bug>61197</bug>: Ensure that the charset name used in the + <code>Content-Type</code> header has exactly the same form as that + provided by the application. This reverts a behavioural change in + 9.0.0.M21 that caused problems for some clients. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org