SPR-8750 Refine 'Content-Type' update in MockHttpServletRequest/Response.

The initial solution kept these three in full sync at all times:
contentType field, characterEncoding field, 'Content-Type' header.
That is correct behavior, however it breaks existing tests that rely
on contentType and characterEncoding being equal to exactly what 
they were set to.

For example, consider:
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");

Ideally both contentType and the 'Content-Type' header would now be
"text/plain;charset=UTF-8". However, existing tests would expect 
that contentType is equal to "text/plain".

To avoid breaking existing tests, contentType and characterEncoding
will continue to be equal to exactly what they were set to while
the 'Content-Type' header will always include both the content 
type and the charset.

The only exception to this rule is when a 'Content-Type' header
is set explicitly, the contentType and characterEncoding fields will 
be updated accordingly, possibly overriding the existing values.
This commit is contained in:
Rossen Stoyanchev 2011-11-17 15:07:15 +00:00
parent 56608d6bd6
commit 63e235f215
11 changed files with 124 additions and 167 deletions

View File

@ -300,18 +300,17 @@ public class MockHttpServletRequest implements HttpServletRequest {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.characterEncoding != null) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public void setContent(byte[] content) {
@ -330,10 +329,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
}
else if (this.characterEncoding != null) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}

View File

@ -140,18 +140,17 @@ public class MockHttpServletResponse implements HttpServletResponse {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
this.charset = true;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.charset) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public String getCharacterEncoding() {
@ -204,11 +203,9 @@ public class MockHttpServletResponse implements HttpServletResponse {
if (charsetIndex != -1) {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
this.charset = true;
}
else if (this.charset) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}

View File

@ -300,18 +300,17 @@ public class MockHttpServletRequest implements HttpServletRequest {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.characterEncoding != null) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public void setContent(byte[] content) {
@ -330,10 +329,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
}
else if (this.characterEncoding != null) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}

View File

@ -139,18 +139,17 @@ public class MockHttpServletResponse implements HttpServletResponse {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
this.charset = true;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.charset) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public String getCharacterEncoding() {
@ -203,11 +202,9 @@ public class MockHttpServletResponse implements HttpServletResponse {
if (charsetIndex != -1) {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
this.charset = true;
}
else if (this.charset) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}

View File

@ -47,7 +47,7 @@ public class MockHttpServletRequestTests extends TestCase {
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testSetContentTypeHeader() {
public void testContentTypeHeader() {
String contentType = "test/plain";
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Content-Type", contentType);
@ -56,7 +56,7 @@ public class MockHttpServletRequestTests extends TestCase {
assertNull(request.getCharacterEncoding());
}
public void testSetContentTypeHeaderUTF8() {
public void testContentTypeHeaderUTF8() {
String contentType = "test/plain;charset=UTF-8";
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Content-Type", contentType);
@ -65,31 +65,20 @@ public class MockHttpServletRequestTests extends TestCase {
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testSetCharacterEncoding() {
String contentType = "test/plain;charset=UTF-8";
public void testSetContentTypeThenCharacterEncoding() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType("test/plain");
request.setCharacterEncoding("UTF-8");
assertEquals(contentType, request.getContentType());
assertEquals(contentType, request.getHeader("Content-Type"));
assertEquals("test/plain", request.getContentType());
assertEquals("test/plain;charset=UTF-8", request.getHeader("Content-Type"));
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testSetCharacterEncodingOppositeOrder() {
String contentType = "test/plain;charset=UTF-8";
public void testSetCharacterEncodingThenContentType() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setCharacterEncoding("UTF-8");
request.setContentType("test/plain");
assertEquals(contentType, request.getContentType());
assertEquals(contentType, request.getHeader("Content-Type"));
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testReplaceCharacterEncoding() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType("test/plain;charset=ISO-8859-1");
request.setCharacterEncoding("UTF-8");
assertEquals("test/plain;charset=UTF-8", request.getContentType());
assertEquals("test/plain", request.getContentType());
assertEquals("test/plain;charset=UTF-8", request.getHeader("Content-Type"));
assertEquals("UTF-8", request.getCharacterEncoding());
}

View File

@ -32,88 +32,84 @@ import org.springframework.web.util.WebUtils;
*/
public class MockHttpServletResponseTests extends TestCase {
public void testSetContentTypeWithNoEncoding() {
public void testSetContentType() {
String contentType = "test/plain";
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType(contentType);
assertEquals("Character encoding should be the default", WebUtils.DEFAULT_CHARACTER_ENCODING,
response.getCharacterEncoding());
assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type"));
assertEquals(contentType, response.getContentType());
assertEquals(contentType, response.getHeader("Content-Type"));
assertEquals(WebUtils.DEFAULT_CHARACTER_ENCODING, response.getCharacterEncoding());
}
public void testSetContentTypeWithUTF8() {
String contentType = "test/plain; charset=UTF-8";
public void testSetContentTypeUTF8() {
String contentType = "test/plain;charset=UTF-8";
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType(contentType);
assertEquals("Character encoding should be 'UTF-8'", "UTF-8", response.getCharacterEncoding());
assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type"));
assertEquals("UTF-8", response.getCharacterEncoding());
assertEquals(contentType, response.getContentType());
assertEquals(contentType, response.getHeader("Content-Type"));
}
public void testContentTypeHeaderWithNoEncoding() {
public void testContentTypeHeader() {
String contentType = "test/plain";
MockHttpServletResponse response = new MockHttpServletResponse();
response.addHeader("Content-Type", contentType);
assertEquals("contentType field not set", contentType, response.getContentType());
assertEquals(contentType, response.getContentType());
assertEquals(contentType, response.getHeader("Content-Type"));
assertEquals(WebUtils.DEFAULT_CHARACTER_ENCODING, response.getCharacterEncoding());
response = new MockHttpServletResponse();
response.setHeader("Content-Type", contentType);
assertEquals("contentType field not set", contentType, response.getContentType());
assertEquals(contentType, response.getContentType());
assertEquals(contentType, response.getHeader("Content-Type"));
assertEquals(WebUtils.DEFAULT_CHARACTER_ENCODING, response.getCharacterEncoding());
}
public void testContentTypeHeaderWithUTF8() {
String contentType = "test/plain; charset=UTF-8";
public void testContentTypeHeaderUTF8() {
String contentType = "test/plain;charset=UTF-8";
MockHttpServletResponse response = new MockHttpServletResponse();
response.setHeader("Content-Type", contentType);
assertEquals(contentType, response.getContentType());
assertEquals(contentType, response.getHeader("Content-Type"));
assertEquals("UTF-8", response.getCharacterEncoding());
response = new MockHttpServletResponse();
response.addHeader("Content-Type", contentType);
assertEquals("contentType field not set", contentType, response.getContentType());
assertEquals("Character encoding should be 'UTF-8'", "UTF-8", response.getCharacterEncoding());
assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type"));
response = new MockHttpServletResponse();
response.setHeader("Content-Type", contentType);
assertEquals("contentType field not set", contentType, response.getContentType());
assertEquals("Character encoding should be 'UTF-8'", "UTF-8", response.getCharacterEncoding());
assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type"));
assertEquals(contentType, response.getContentType());
assertEquals(contentType, response.getHeader("Content-Type"));
assertEquals("UTF-8", response.getCharacterEncoding());
}
public void testSetCharacterEncoding() {
public void testSetContentTypeThenCharacterEncoding() {
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType("test/plain");
response.setCharacterEncoding("UTF-8");
assertEquals("Character encoding not set", "UTF-8", response.getCharacterEncoding());
assertEquals("contentType field not set", "test/plain;charset=UTF-8", response.getContentType());
assertEquals("Content-Type header not set", "test/plain;charset=UTF-8", response.getHeader("Content-Type"));
assertEquals("test/plain", response.getContentType());
assertEquals("test/plain;charset=UTF-8", response.getHeader("Content-Type"));
assertEquals("UTF-8", response.getCharacterEncoding());
}
public void testSetCharacterEncodingOppositeOrder() {
public void testSetCharacterEncodingThenContentType() {
MockHttpServletResponse response = new MockHttpServletResponse();
response.setCharacterEncoding("UTF-8");
response.setContentType("test/plain");
assertEquals("Character encoding not set", "UTF-8", response.getCharacterEncoding());
assertEquals("contentType field not set", "test/plain;charset=UTF-8", response.getContentType());
assertEquals("Content-Type header not set", "test/plain;charset=UTF-8", response.getHeader("Content-Type"));
assertEquals("test/plain", response.getContentType());
assertEquals("test/plain;charset=UTF-8", response.getHeader("Content-Type"));
assertEquals("UTF-8", response.getCharacterEncoding());
}
public void testReplaceCharacterEncoding() {
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType("test/plain;charset=ISO-8859-1");
response.setCharacterEncoding("UTF-8");
assertEquals("Character encoding not set", "UTF-8", response.getCharacterEncoding());
assertEquals("contentType field not set", "test/plain;charset=UTF-8", response.getContentType());
assertEquals("Content-Type header not set", "test/plain;charset=UTF-8", response.getHeader("Content-Type"));
}
public void testContentLength() {
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentLength(66);
assertEquals("Content length field not set", 66, response.getContentLength());
assertEquals("Content-Length header not set", "66", response.getHeader("Content-Length"));
assertEquals(66, response.getContentLength());
assertEquals("66", response.getHeader("Content-Length"));
}
public void testContentLengthHeader() {
MockHttpServletResponse response = new MockHttpServletResponse();
response.addHeader("Content-Length", "66");
assertEquals("Content length field not set", 66, response.getContentLength());
assertEquals("Content-Length header not set", "66", response.getHeader("Content-Length"));
assertEquals(66,response.getContentLength());
assertEquals("66", response.getHeader("Content-Length"));
}
public void testHttpHeaderNameCasingIsPreserved() throws Exception {

View File

@ -310,18 +310,17 @@ public class MockHttpServletRequest implements HttpServletRequest {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.characterEncoding != null) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public void setContent(byte[] content) {
@ -340,10 +339,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
}
else if (this.characterEncoding != null) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}

View File

@ -145,18 +145,17 @@ public class MockHttpServletResponse implements HttpServletResponse {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
this.charset = true;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.charset) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public String getCharacterEncoding() {
@ -209,11 +208,9 @@ public class MockHttpServletResponse implements HttpServletResponse {
if (charsetIndex != -1) {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
this.charset = true;
}
else if (this.charset) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}

View File

@ -92,7 +92,7 @@ public class MappingJacksonJsonViewTest {
assertEquals("no-cache, no-store, max-age=0", response.getHeader("Cache-Control"));
assertNotNull(response.getHeader("Expires"));
assertEquals(MappingJacksonJsonView.DEFAULT_CONTENT_TYPE + ";charset=UTF-8", response.getContentType());
assertEquals(MappingJacksonJsonView.DEFAULT_CONTENT_TYPE, response.getContentType());
String jsonResult = response.getContentAsString();
assertTrue(jsonResult.length() > 0);

View File

@ -310,18 +310,17 @@ public class MockHttpServletRequest implements HttpServletRequest {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.characterEncoding != null) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public void setContent(byte[] content) {
@ -340,10 +339,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
}
else if (this.characterEncoding != null) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}

View File

@ -144,18 +144,17 @@ public class MockHttpServletResponse implements HttpServletResponse {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
this.charset = true;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
updateContentTypeHeader();
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
private void updateContentTypeHeader() {
if (this.contentType != null) {
StringBuilder sb = new StringBuilder(this.contentType);
if (this.contentType.toLowerCase().indexOf(CHARSET_PREFIX) == -1 && this.charset) {
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
}
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
}
return contentType;
}
public String getCharacterEncoding() {
@ -208,11 +207,9 @@ public class MockHttpServletResponse implements HttpServletResponse {
if (charsetIndex != -1) {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
this.characterEncoding = encoding;
this.charset = true;
}
else if (this.charset) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
updateContentTypeHeader();
}
}