Issue #608 reset encoding set from content type

Use an enum to track where a content encoding came from and selectively clear/reset
This commit is contained in:
Greg Wilkins 2016-06-01 15:28:04 +10:00
parent 2508d73a94
commit c2831bf09c
2 changed files with 69 additions and 14 deletions

View File

@ -24,6 +24,7 @@ import java.nio.channels.IllegalSelectorException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Locale;
@ -108,12 +109,15 @@ public class Response implements HttpServletResponse
private Locale _locale;
private MimeTypes.Type _mimeType;
private String _characterEncoding;
private boolean _explicitEncoding;
private EncodingFrom _encodingFrom=EncodingFrom.NOT_SET;
private String _contentType;
private OutputType _outputType = OutputType.NONE;
private ResponseWriter _writer;
private long _contentLength = -1;
private enum EncodingFrom { NOT_SET, INFERRED, SET_LOCALE, SET_CONTENT_TYPE, SET_CHARACTER_ENCODING };
private static final EnumSet<EncodingFrom> __localeOverride = EnumSet.of(EncodingFrom.NOT_SET,EncodingFrom.INFERRED);
public Response(HttpChannel channel, HttpOutput out)
{
@ -138,7 +142,7 @@ public class Response implements HttpServletResponse
_contentLength = -1;
_out.recycle();
_fields.clear();
_explicitEncoding=false;
_encodingFrom=EncodingFrom.NOT_SET;
}
public HttpOutput getHttpOutput()
@ -899,7 +903,7 @@ public class Response implements HttpServletResponse
encoding = MimeTypes.inferCharsetFromContentType(_contentType);
if (encoding == null)
encoding = StringUtil.__ISO_8859_1;
setCharacterEncoding(encoding,false);
setCharacterEncoding(encoding,EncodingFrom.INFERRED);
}
}
@ -1015,10 +1019,10 @@ public class Response implements HttpServletResponse
@Override
public void setCharacterEncoding(String encoding)
{
setCharacterEncoding(encoding,true);
setCharacterEncoding(encoding,EncodingFrom.SET_CHARACTER_ENCODING);
}
private void setCharacterEncoding(String encoding, boolean explicit)
private void setCharacterEncoding(String encoding, EncodingFrom from)
{
if (isIncluding() || isWriting())
return;
@ -1027,7 +1031,7 @@ public class Response implements HttpServletResponse
{
if (encoding == null)
{
_explicitEncoding=false;
_encodingFrom=EncodingFrom.NOT_SET;
// Clear any encoding.
if (_characterEncoding != null)
@ -1050,7 +1054,7 @@ public class Response implements HttpServletResponse
else
{
// No, so just add this one to the mimetype
_explicitEncoding = explicit;
_encodingFrom = from;
_characterEncoding = HttpGenerator.__STRICT?encoding:StringUtil.normalizeCharset(encoding);
if (_mimeType!=null)
{
@ -1100,10 +1104,29 @@ public class Response implements HttpServletResponse
if (charset == null)
{
if (_characterEncoding != null)
switch (_encodingFrom)
{
_contentType = contentType + ";charset=" + _characterEncoding;
_mimeType = null;
case NOT_SET:
break;
case INFERRED:
case SET_CONTENT_TYPE:
if (isWriting())
{
_mimeType=null;
_contentType = _contentType + ";charset=" + _characterEncoding;
}
else
{
_encodingFrom=EncodingFrom.NOT_SET;
_characterEncoding=null;
}
break;
case SET_LOCALE:
case SET_CHARACTER_ENCODING:
{
_contentType = contentType + ";charset=" + _characterEncoding;
_mimeType = null;
}
}
}
else if (isWriting() && !charset.equalsIgnoreCase(_characterEncoding))
@ -1117,7 +1140,7 @@ public class Response implements HttpServletResponse
else
{
_characterEncoding = charset;
_explicitEncoding = true;
_encodingFrom = EncodingFrom.SET_CONTENT_TYPE;
}
if (HttpGenerator.__STRICT || _mimeType==null)
@ -1268,8 +1291,8 @@ public class Response implements HttpServletResponse
String charset = _channel.getRequest().getContext().getContextHandler().getLocaleEncoding(locale);
if (charset != null && charset.length() > 0 && !_explicitEncoding)
setCharacterEncoding(charset,false);
if (charset != null && charset.length() > 0 && __localeOverride.contains(_encodingFrom))
setCharacterEncoding(charset,EncodingFrom.SET_LOCALE);
}
@Override

View File

@ -165,7 +165,7 @@ public class ResponseTest
assertEquals("text/html", response.getContentType());
response.getWriter();
assertEquals("text/html;charset=utf-8", response.getContentType());
response.setContentType("foo2/bar2");
response.setContentType("foo2/bar2;charset=utf-8");
assertEquals("foo2/bar2;charset=utf-8", response.getContentType());
response.recycle();
@ -357,6 +357,38 @@ public class ResponseTest
assertEquals("text/xml;charset=utf-8", response.getContentType());
}
@Test
public void testResetContentTypeWithoutCharacterEncoding() throws Exception
{
Response response = newResponse();
response.setCharacterEncoding("utf-8");
response.setContentType("wrong/answer");
response.setContentType("foo/bar");
assertEquals("foo/bar;charset=utf-8", response.getContentType());
response.getWriter();
response.setContentType("foo2/bar2");
assertEquals("foo2/bar2;charset=utf-8", response.getContentType());
}
@Test
public void testResetContentTypeWithCharacterEncoding() throws Exception
{
Response response = newResponse();
response.setContentType("wrong/answer;charset=utf-8");
response.setContentType("foo/bar");
assertEquals("foo/bar", response.getContentType());
response.setContentType("wrong/answer;charset=utf-8");
response.getWriter();
response.setContentType("foo2/bar2;charset=utf-16");
assertEquals("foo2/bar2;charset=utf-8", response.getContentType());
}
@Test
public void testContentTypeWithOther() throws Exception
{