Bug 64938

Summary: response.setCharacterEncoding(null) should clear previous charset
Product: Tomcat 9 Reporter: quaff <zhouyanming>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: unspecified   
Target Milestone: -----   
Hardware: PC   
OS: Mac OS X 10.4   

Description quaff 2020-11-27 08:43:54 UTC
I have a filter set response charset to UTF-8 globally, one of my servlets want remove charset encoding from response Content-Type, for example 
response.setCharacterEncoding(null);
response.setContentType("application/wasm");
It still generate invalid "application/wasm;charset=UTF-8" because "response.setCharacterEncoding(null)" is noop, currently there is no way to clear previous charset.

https://github.com/apache/tomcat/blob/master/java/org/apache/coyote/Response.java#L502
Comment 2 Mark Thomas 2020-11-27 09:17:12 UTC
The behaviour of other Servlet containers is irrelevant. What matters is the Sevlet specification.

You could argue that the ServletResponse.setCharacterEncoding Javadoc does not permit null to be passed as the character set. Neither does it define the failure mode if an invalid character encoding is specified. This is one of the many areas where the spec could be better defined.

One workaround may be to define the default character encoding in web.xml with:

<response-character-encoding>UTF-8</response-character-encoding>

rather than via the filter. Although that won't help if some resources require UTF-8 to be set explicitly.

Another possible workaround is ServletResponse.reset().

The interplay of setLocale(), setContentType() and setChjaracterEncoding() along with getWriter() and the web.xml default encoding (and probably at least one other bit I have forgotten) means that this might not be as simple as it first looks.

I can see the use case for being able to use null here so I'm planning on looking at this later today with a view to implementing it. I'll also see if we can get the Javadoc clarified that null undoes any previous call (assuming getWriter() hasn't been called etc.)
Comment 3 Remy Maucherat 2020-11-27 09:40:42 UTC
According to the javadoc, null is probably not a valid value (it says: "charset: a String specifying only the character set defined by IANA", so "null" is obviously not one of these). Unlike other places, it is not specified to throw an IAE or something like that.
Comment 4 Mark Thomas 2020-11-27 11:58:05 UTC
The current Javadoc certainly implies null is not valid here but I can see how allowing it might be useful.

I've opened https://github.com/eclipse-ee4j/servlet-api/issues/377

Switching to NEEDINFO as the way forward will be guided by how the spec project decides to clarify this.
Comment 5 Mark Thomas 2021-02-04 10:39:42 UTC
The spec project has provided clarification via updated Javadoc. Strictly that only applies to the next iteration of the Servlet spec but do I intend to look at applying this to current Tomcat versions.
Comment 6 Mark Thomas 2021-02-23 13:10:00 UTC
I've implemented the changes agreed in the Jakarta Servlet project for 10.0.x. They will be in 10.0.3 onwards.

I have started a discussion on the dev@ list to determine if the changes should be back-ported and how configurable - if at all - they should be in earlier versions.
Comment 7 Mark Thomas 2021-03-01 15:12:22 UTC
Fixed in:
- 10.0.x for 10.0.3 onwards
- 9.0.x for 9.0.44 onwards
- 8.5.x for 8.5.64 onwards