MockHttpServletRequestBuilder parses form data

Spring MVC Test now parses application/x-www-form-urlencoded request
content and populates request parameters from it.

This can be useful when running client-side tests against a MockMvc
via MockMvcClientHttpRequestFactory.

Issue: SPR-13733
This commit is contained in:
Rossen Stoyanchev
2016-01-21 17:20:34 -05:00
parent 6a9455b7d0
commit 415b2763ce
3 changed files with 69 additions and 18 deletions

View File

@@ -16,6 +16,9 @@
package org.springframework.test.web.servlet.request;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.Principal;
@@ -33,8 +36,10 @@ import javax.servlet.http.Cookie;
import org.springframework.beans.Mergeable;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
@@ -603,24 +608,10 @@ public class MockHttpServletRequestBuilder
}
}
try {
if (this.url.getRawQuery() != null) {
request.setQueryString(this.url.getRawQuery());
}
MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUri(this.url).build().getQueryParams();
for (Entry<String, List<String>> entry : queryParams.entrySet()) {
for (String value : entry.getValue()) {
value = (value != null) ? UriUtils.decode(value, "UTF-8") : null;
request.addParameter(UriUtils.decode(entry.getKey(), "UTF-8"), value);
}
}
}
catch (UnsupportedEncodingException ex) {
// shouldn't happen
if (this.url.getRawQuery() != null) {
request.setQueryString(this.url.getRawQuery());
}
addRequestParams(request, UriComponentsBuilder.fromUri(this.url).build().getQueryParams());
for (String name : this.parameters.keySet()) {
for (String value : this.parameters.get(name)) {
@@ -632,6 +623,13 @@ public class MockHttpServletRequestBuilder
request.setContent(this.content);
request.setCharacterEncoding(this.characterEncoding);
if (this.content != null && this.contentType != null) {
MediaType mediaType = MediaType.parseMediaType(this.contentType);
if (MediaType.APPLICATION_FORM_URLENCODED.includes(mediaType)) {
addRequestParams(request, parseFormData(mediaType));
}
}
if (!ObjectUtils.isEmpty(this.cookies)) {
request.setCookies(this.cookies.toArray(new Cookie[this.cookies.size()]));
}
@@ -695,6 +693,43 @@ public class MockHttpServletRequestBuilder
request.setPathInfo(this.pathInfo);
}
private void addRequestParams(MockHttpServletRequest request, MultiValueMap<String, String> map) {
try {
for (Entry<String, List<String>> entry : map.entrySet()) {
for (String value : entry.getValue()) {
value = (value != null) ? UriUtils.decode(value, "UTF-8") : null;
request.addParameter(UriUtils.decode(entry.getKey(), "UTF-8"), value);
}
}
}
catch (UnsupportedEncodingException ex) {
// shouldn't happen
}
}
private MultiValueMap<String, String> parseFormData(final MediaType mediaType) {
MultiValueMap<String, String> map;HttpInputMessage message = new HttpInputMessage() {
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(content);
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(mediaType);
return headers;
}
};
try {
map = new FormHttpMessageConverter().read(null, message);
}
catch (IOException ex) {
throw new IllegalStateException("Failed to parse form data in request body: ", ex);
}
return map;
}
private FlashMapManager getFlashMapManager(MockHttpServletRequest request) {
FlashMapManager flashMapManager = null;
try {