SPR-8750 Update MockHttpServletRequest/Response handling of contentType.

The Content-Type header and the contentType field in HttpServletRequest/Response
are now always in sync. When a header is added the contentType field is updated
as well and vice versa. 

Similarly when the Content-Type header or the contentType field includes a charset 
field, the character encoding is updated and vice versa.
This commit is contained in:
Rossen Stoyanchev
2011-11-16 23:28:48 +00:00
parent 3528637d62
commit 7918810366
13 changed files with 474 additions and 18 deletions

View File

@@ -92,6 +92,11 @@ public class MockHttpServletRequest implements HttpServletRequest {
*/
public static final String DEFAULT_REMOTE_HOST = "localhost";
private static final String CONTENT_TYPE_HEADER = "Content-Type";
private static final String CHARSET_PREFIX = "charset=";
private boolean active = true;
@@ -295,6 +300,18 @@ public class MockHttpServletRequest implements HttpServletRequest {
public void setCharacterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
if (this.contentType != null) {
String type = removeCharset(this.contentType);
setContentType(type);
}
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
}
return contentType;
}
public void setContent(byte[] content) {
@@ -307,6 +324,17 @@ public class MockHttpServletRequest implements HttpServletRequest {
public void setContentType(String contentType) {
this.contentType = contentType;
if (contentType != null) {
int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (charsetIndex != -1) {
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);
}
}
public String getContentType() {
@@ -642,11 +670,19 @@ public class MockHttpServletRequest implements HttpServletRequest {
* @see #getDateHeader
* @see #getIntHeader
*/
@SuppressWarnings("rawtypes")
public void addHeader(String name, Object value) {
if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) {
setContentType((String) value);
return;
}
doAddHeaderValue(name, value, false);
}
@SuppressWarnings("rawtypes")
private void doAddHeaderValue(String name, Object value, boolean replace) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
Assert.notNull(value, "Header value must not be null");
if (header == null) {
if (header == null || replace) {
header = new HeaderValueHolder();
this.headers.put(name, header);
}

View File

@@ -50,6 +50,9 @@ public class MockHttpServletResponse implements HttpServletResponse {
private static final String CHARSET_PREFIX = "charset=";
private static final String CONTENT_TYPE_HEADER = "Content-Type";
private static final String CONTENT_LENGTH_HEADER = "Content-Length";
//---------------------------------------------------------------------
// ServletResponse properties
@@ -60,6 +63,8 @@ public class MockHttpServletResponse implements HttpServletResponse {
private boolean writerAccessAllowed = true;
private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING;
private boolean charset = false;
private final ByteArrayOutputStream content = new ByteArrayOutputStream();
@@ -133,8 +138,21 @@ 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);
}
}
private String removeCharset(String contentType) {
int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (index != -1) {
contentType = contentType.substring(0, contentType.lastIndexOf(';', index));
}
return contentType;
}
public String getCharacterEncoding() {
return this.characterEncoding;
}
@@ -171,6 +189,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
public void setContentLength(int contentLength) {
this.contentLength = contentLength;
doAddHeaderValue(CONTENT_LENGTH_HEADER, contentLength, true);
}
public int getContentLength() {
@@ -183,8 +202,12 @@ public class MockHttpServletResponse implements HttpServletResponse {
int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
if (charsetIndex != -1) {
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
setCharacterEncoding(encoding);
this.characterEncoding = encoding;
}
else if (this.charset) {
this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding;
}
doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true);
}
}
@@ -424,12 +447,32 @@ public class MockHttpServletResponse implements HttpServletResponse {
}
private void setHeaderValue(String name, Object value) {
if (setSpecialHeader(name, value)) {
return;
}
doAddHeaderValue(name, value, true);
}
private void addHeaderValue(String name, Object value) {
if (setSpecialHeader(name, value)) {
return;
}
doAddHeaderValue(name, value, false);
}
private boolean setSpecialHeader(String name, Object value) {
if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) {
setContentType((String) value);
return true;
}
else if (CONTENT_LENGTH_HEADER.equalsIgnoreCase(name)) {
setContentLength(Integer.parseInt((String) value));
return true;
}
else {
return false;
}
}
private void doAddHeaderValue(String name, Object value, boolean replace) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,9 +25,75 @@ import junit.framework.TestCase;
/**
* @author Rick Evans
* @author Mark Fisher
* @author Rossen Stoyanchev
*/
public class MockHttpServletRequestTests extends TestCase {
public void testSetContentType() {
String contentType = "test/plain";
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType(contentType);
assertEquals(contentType, request.getContentType());
assertEquals(contentType, request.getHeader("Content-Type"));
assertNull(request.getCharacterEncoding());
}
public void testSetContentTypeUTF8() {
String contentType = "test/plain;charset=UTF-8";
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType(contentType);
assertEquals(contentType, request.getContentType());
assertEquals(contentType, request.getHeader("Content-Type"));
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testSetContentTypeHeader() {
String contentType = "test/plain";
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Content-Type", contentType);
assertEquals(contentType, request.getContentType());
assertEquals(contentType, request.getHeader("Content-Type"));
assertNull(request.getCharacterEncoding());
}
public void testSetContentTypeHeaderUTF8() {
String contentType = "test/plain;charset=UTF-8";
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Content-Type", contentType);
assertEquals(contentType, request.getContentType());
assertEquals(contentType, request.getHeader("Content-Type"));
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testSetCharacterEncoding() {
String contentType = "test/plain;charset=UTF-8";
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType("test/plain");
request.setCharacterEncoding("UTF-8");
assertEquals(contentType, request.getContentType());
assertEquals(contentType, request.getHeader("Content-Type"));
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testSetCharacterEncodingOppositeOrder() {
String contentType = "test/plain;charset=UTF-8";
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;charset=UTF-8", request.getHeader("Content-Type"));
assertEquals("UTF-8", request.getCharacterEncoding());
}
public void testHttpHeaderNameCasingIsPreserved() throws Exception {
String headerName = "Header1";
MockHttpServletRequest request = new MockHttpServletRequest();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,23 +27,95 @@ import org.springframework.web.util.WebUtils;
/**
* @author Juergen Hoeller
* @author Rick Evans
* @author Rossen Stoyanchev
* @since 19.02.2006
*/
public class MockHttpServletResponseTests extends TestCase {
public void testSetContentTypeWithNoEncoding() {
String contentType = "test/plain";
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType("test/plain");
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"));
}
public void testSetContentTypeWithUTF8() {
String contentType = "test/plain; charset=UTF-8";
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType("test/plain; charset=UTF-8");
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"));
}
public void testContentTypeHeaderWithNoEncoding() {
String contentType = "test/plain";
MockHttpServletResponse response = new MockHttpServletResponse();
response.addHeader("Content-Type", contentType);
assertEquals("contentType field not set", contentType, response.getContentType());
response = new MockHttpServletResponse();
response.setHeader("Content-Type", contentType);
assertEquals("contentType field not set", contentType, response.getContentType());
}
public void testContentTypeHeaderWithUTF8() {
String contentType = "test/plain; charset=UTF-8";
MockHttpServletResponse 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"));
}
public void testSetCharacterEncoding() {
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"));
}
public void testSetCharacterEncodingOppositeOrder() {
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"));
}
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"));
}
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"));
}
public void testHttpHeaderNameCasingIsPreserved() throws Exception {
final String headerName = "Header1";