diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java index c5b527b4adab..51be1286e5d7 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java @@ -294,7 +294,8 @@ public MockHttpServletRequestBuilder contentType(MediaType contentType) { * @since 4.1.2 */ public MockHttpServletRequestBuilder contentType(String contentType) { - this.contentType = MediaType.parseMediaType(contentType).toString(); + Assert.notNull(contentType, "'contentType' must not be null"); + this.contentType = contentType; return this; } @@ -314,11 +315,9 @@ public MockHttpServletRequestBuilder accept(MediaType... mediaTypes) { */ public MockHttpServletRequestBuilder accept(String... mediaTypes) { Assert.notEmpty(mediaTypes, "'mediaTypes' must not be empty"); - List result = new ArrayList<>(mediaTypes.length); - for (String mediaType : mediaTypes) { - result.add(MediaType.parseMediaType(mediaType)); - } - this.headers.set("Accept", MediaType.toString(result)); + List result = new ArrayList<>(mediaTypes.length); + result.addAll(Arrays.asList(mediaTypes)); + this.headers.set("Accept", String.join(", ", result)); return this; } @@ -712,7 +711,7 @@ public final MockHttpServletRequest buildRequest(ServletContext servletContext) if (this.content != null && this.content.length > 0) { String requestContentType = request.getContentType(); - if (requestContentType != null) { + if (requestContentType != null && isValidContentType(requestContentType)) { MediaType mediaType = MediaType.parseMediaType(requestContentType); if (MediaType.APPLICATION_FORM_URLENCODED.includes(mediaType)) { addRequestParams(request, parseFormData(mediaType)); @@ -742,6 +741,26 @@ public final MockHttpServletRequest buildRequest(ServletContext servletContext) return request; } + /** + * Some validation checks to find out if processing of a string value make sense. + */ + private boolean isValidContentType(String mimeType) { + if (!StringUtils.hasLength(mimeType)) { + return false; + } + + int index = mimeType.indexOf(';'); + String fullType = (index >= 0 ? mimeType.substring(0, index) : mimeType).trim(); + if (fullType.isEmpty()) { + return false; + } + int subIndex = fullType.indexOf('/'); + if (subIndex == -1) { + return false; + } + return subIndex != fullType.length() - 1; + } + /** * Create a new {@link MockHttpServletRequest} based on the supplied * {@code ServletContext}. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java index ae111d7877b6..3479d385e622 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java @@ -29,6 +29,8 @@ import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.servlet.ServletContext; import javax.servlet.http.Cookie; @@ -337,6 +339,21 @@ public void acceptHeader() { assertThat(result.get(1).toString()).isEqualTo("application/xml"); } + @Test + public void anyAcceptMultipleContentTypeViaStringArray() { + this.builder.accept("any", "any2"); + + MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); + List accept = Collections.list(request.getHeaders("Accept")); + List result = Stream.of(accept.get(0).split(",")) + .map(String::trim) + .collect(Collectors.toList()); + + assertThat(result.get(0)).isEqualTo("any"); + assertThat(result).hasSize(2); + assertThat(result.get(1)).isEqualTo("any2"); + } + @Test public void contentType() { this.builder.contentType(MediaType.TEXT_HTML); @@ -363,6 +380,19 @@ public void contentTypeViaString() { assertThat(contentTypes.get(0)).isEqualTo("text/html"); } + @Test + public void anyContentTypeViaString() { + this.builder.contentType("any"); + + MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); + String contentType = request.getContentType(); + List contentTypes = Collections.list(request.getHeaders("Content-Type")); + + assertThat(contentType).isEqualTo("any"); + assertThat(contentTypes).hasSize(1); + assertThat(contentTypes.get(0)).isEqualTo("any"); + } + @Test // SPR-11308 public void contentTypeViaHeader() { this.builder.header("Content-Type", MediaType.TEXT_HTML_VALUE); @@ -372,6 +402,16 @@ public void contentTypeViaHeader() { assertThat(contentType).isEqualTo("text/html"); } + @Test // SPR-17643 + public void invalidContentTypeViaHeader() { + this.builder.header("Content-Type", "yaml"); + this.builder.content("some content"); + MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); + String contentType = request.getContentType(); + + assertThat(contentType).isEqualTo("yaml"); + } + @Test // SPR-11308 public void contentTypeViaMultipleHeaderValues() { this.builder.header("Content-Type", MediaType.TEXT_HTML_VALUE, MediaType.ALL_VALUE);