Skip to content

Commit 4ab27d8

Browse files
committed
Consistently accept empty Content-Type header and empty character encoding
Issue: SPR-12173 (cherry picked from commit a1c0905)
1 parent de3ea5d commit 4ab27d8

File tree

4 files changed

+65
-31
lines changed

4 files changed

+65
-31
lines changed

spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@
4747

4848
import org.springframework.util.Assert;
4949
import org.springframework.util.LinkedCaseInsensitiveMap;
50+
import org.springframework.util.StringUtils;
5051

5152
/**
5253
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest} interface.
@@ -210,8 +211,8 @@ public MockHttpServletRequest(String method, String requestURI) {
210211

211212
/**
212213
* Create a new {@code MockHttpServletRequest} with the supplied {@link ServletContext}.
213-
* @param servletContext the ServletContext that the request runs in (may be
214-
* {@code null} to use a default {@link MockServletContext})
214+
* @param servletContext the ServletContext that the request runs in
215+
* (may be {@code null} to use a default {@link MockServletContext})
215216
* @see #MockHttpServletRequest(ServletContext, String, String)
216217
*/
217218
public MockHttpServletRequest(ServletContext servletContext) {
@@ -308,9 +309,10 @@ public void setCharacterEncoding(String characterEncoding) {
308309
}
309310

310311
private void updateContentTypeHeader() {
311-
if (this.contentType != null) {
312+
if (StringUtils.hasLength(this.contentType)) {
312313
StringBuilder sb = new StringBuilder(this.contentType);
313-
if (!this.contentType.toLowerCase().contains(CHARSET_PREFIX) && this.characterEncoding != null) {
314+
if (!this.contentType.toLowerCase().contains(CHARSET_PREFIX) &&
315+
StringUtils.hasLength(this.characterEncoding)) {
314316
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
315317
}
316318
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
@@ -330,8 +332,7 @@ public void setContentType(String contentType) {
330332
if (contentType != null) {
331333
int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
332334
if (charsetIndex != -1) {
333-
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
334-
this.characterEncoding = encoding;
335+
this.characterEncoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
335336
}
336337
updateContentTypeHeader();
337338
}
@@ -715,8 +716,8 @@ else if (value instanceof Number) {
715716
return ((Number) value).longValue();
716717
}
717718
else if (value != null) {
718-
throw new IllegalArgumentException("Value for header '" + name + "' is neither a Date nor a Number: "
719-
+ value);
719+
throw new IllegalArgumentException(
720+
"Value for header '" + name + "' is neither a Date nor a Number: " + value);
720721
}
721722
else {
722723
return -1L;

spring-web/src/main/java/org/springframework/http/server/ServletServerHttpRequest.java

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import java.nio.charset.Charset;
2929
import java.util.Arrays;
3030
import java.util.Enumeration;
31-
import java.util.HashMap;
3231
import java.util.Iterator;
3332
import java.util.List;
3433
import java.util.Map;
@@ -38,6 +37,8 @@
3837
import org.springframework.http.HttpMethod;
3938
import org.springframework.http.MediaType;
4039
import org.springframework.util.Assert;
40+
import org.springframework.util.LinkedCaseInsensitiveMap;
41+
import org.springframework.util.StringUtils;
4142

4243
/**
4344
* {@link ServerHttpRequest} implementation that is based on a {@link HttpServletRequest}.
@@ -103,21 +104,30 @@ public HttpHeaders getHeaders() {
103104
}
104105
}
105106
// HttpServletRequest exposes some headers as properties: we should include those if not already present
106-
if (this.headers.getContentType() == null && this.servletRequest.getContentType() != null) {
107-
MediaType contentType = MediaType.parseMediaType(this.servletRequest.getContentType());
108-
this.headers.setContentType(contentType);
107+
MediaType contentType = this.headers.getContentType();
108+
if (contentType == null) {
109+
String requestContentType = this.servletRequest.getContentType();
110+
if (StringUtils.hasLength(requestContentType)) {
111+
contentType = MediaType.parseMediaType(requestContentType);
112+
this.headers.setContentType(contentType);
113+
}
109114
}
110-
if (this.headers.getContentType() != null && this.headers.getContentType().getCharSet() == null &&
111-
this.servletRequest.getCharacterEncoding() != null) {
112-
MediaType oldContentType = this.headers.getContentType();
113-
Charset charSet = Charset.forName(this.servletRequest.getCharacterEncoding());
114-
Map<String, String> params = new HashMap<String, String>(oldContentType.getParameters());
115-
params.put("charset", charSet.toString());
116-
MediaType newContentType = new MediaType(oldContentType.getType(), oldContentType.getSubtype(), params);
117-
this.headers.setContentType(newContentType);
115+
if (contentType != null && contentType.getCharSet() == null) {
116+
String requestEncoding = this.servletRequest.getCharacterEncoding();
117+
if (StringUtils.hasLength(requestEncoding)) {
118+
Charset charSet = Charset.forName(requestEncoding);
119+
Map<String, String> params = new LinkedCaseInsensitiveMap<String>();
120+
params.putAll(contentType.getParameters());
121+
params.put("charset", charSet.toString());
122+
MediaType newContentType = new MediaType(contentType.getType(), contentType.getSubtype(), params);
123+
this.headers.setContentType(newContentType);
124+
}
118125
}
119-
if (this.headers.getContentLength() == -1 && this.servletRequest.getContentLength() != -1) {
120-
this.headers.setContentLength(this.servletRequest.getContentLength());
126+
if (this.headers.getContentLength() == -1) {
127+
int requestContentLength = this.servletRequest.getContentLength();
128+
if (requestContentLength != -1) {
129+
this.headers.setContentLength(requestContentLength);
130+
}
121131
}
122132
}
123133
return this.headers;

spring-web/src/test/java/org/springframework/http/server/ServletServerHttpRequestTests.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,12 +40,14 @@ public class ServletServerHttpRequestTests {
4040

4141
private MockHttpServletRequest mockRequest;
4242

43+
4344
@Before
4445
public void create() throws Exception {
4546
mockRequest = new MockHttpServletRequest();
4647
request = new ServletServerHttpRequest(mockRequest);
4748
}
4849

50+
4951
@Test
5052
public void getMethod() throws Exception {
5153
mockRequest.setMethod("POST");
@@ -66,8 +68,8 @@ public void getURI() throws Exception {
6668
public void getHeaders() throws Exception {
6769
String headerName = "MyHeader";
6870
String headerValue1 = "value1";
69-
mockRequest.addHeader(headerName, headerValue1);
7071
String headerValue2 = "value2";
72+
mockRequest.addHeader(headerName, headerValue1);
7173
mockRequest.addHeader(headerName, headerValue2);
7274
mockRequest.setContentType("text/plain");
7375
mockRequest.setCharacterEncoding("UTF-8");
@@ -83,6 +85,26 @@ public void getHeaders() throws Exception {
8385
headers.getContentType());
8486
}
8587

88+
@Test
89+
public void getHeadersWithEmptyContentTypeAndEncoding() throws Exception {
90+
String headerName = "MyHeader";
91+
String headerValue1 = "value1";
92+
String headerValue2 = "value2";
93+
mockRequest.addHeader(headerName, headerValue1);
94+
mockRequest.addHeader(headerName, headerValue2);
95+
mockRequest.setContentType("");
96+
mockRequest.setCharacterEncoding("");
97+
98+
HttpHeaders headers = request.getHeaders();
99+
assertNotNull("No HttpHeaders returned", headers);
100+
assertTrue("Invalid headers returned", headers.containsKey(headerName));
101+
List<String> headerValues = headers.get(headerName);
102+
assertEquals("Invalid header values returned", 2, headerValues.size());
103+
assertTrue("Invalid header values returned", headerValues.contains(headerValue1));
104+
assertTrue("Invalid header values returned", headerValues.contains(headerValue2));
105+
assertNull(headers.getContentType());
106+
}
107+
86108
@Test
87109
public void getBody() throws Exception {
88110
byte[] content = "Hello World".getBytes("UTF-8");
@@ -106,4 +128,4 @@ public void getFormBody() throws Exception {
106128
assertArrayEquals("Invalid content returned", content, result);
107129
}
108130

109-
}
131+
}

spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@
5252

5353
import org.springframework.util.Assert;
5454
import org.springframework.util.LinkedCaseInsensitiveMap;
55+
import org.springframework.util.StringUtils;
5556

5657
/**
5758
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
@@ -331,9 +332,10 @@ public void setCharacterEncoding(String characterEncoding) {
331332
}
332333

333334
private void updateContentTypeHeader() {
334-
if (this.contentType != null) {
335+
if (StringUtils.hasLength(this.contentType)) {
335336
StringBuilder sb = new StringBuilder(this.contentType);
336-
if (!this.contentType.toLowerCase().contains(CHARSET_PREFIX) && this.characterEncoding != null) {
337+
if (!this.contentType.toLowerCase().contains(CHARSET_PREFIX) &&
338+
StringUtils.hasLength(this.characterEncoding)) {
337339
sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding);
338340
}
339341
doAddHeaderValue(CONTENT_TYPE_HEADER, sb.toString(), true);
@@ -354,8 +356,7 @@ public void setContentType(String contentType) {
354356
if (contentType != null) {
355357
int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
356358
if (charsetIndex != -1) {
357-
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
358-
this.characterEncoding = encoding;
359+
this.characterEncoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
359360
}
360361
updateContentTypeHeader();
361362
}

0 commit comments

Comments
 (0)