MockMvc request builder preserves double slashes

The MockHttpServletRequestBuilder now uses java.net.URI internally
rather than UriComponents.

This means that for the MockMvcRequestBuilders method variants that
accept a java.net.URI we can use it as is. The difference is almost
none but it does mean that you can create a URI with double slashes
(for testing purposes) and have it remain that way.

Issue: SPR-13435
This commit is contained in:
Rossen Stoyanchev
2015-09-23 17:50:29 -04:00
parent fb3e054a31
commit df171ff5bb
2 changed files with 34 additions and 23 deletions

View File

@@ -51,7 +51,6 @@ import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.support.SessionFlashMapManager; import org.springframework.web.servlet.support.SessionFlashMapManager;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils; import org.springframework.web.util.UriUtils;
@@ -72,7 +71,7 @@ public class MockHttpServletRequestBuilder
private final HttpMethod method; private final HttpMethod method;
private final UriComponents uriComponents; private final URI url;
private final MultiValueMap<String, Object> headers = new LinkedMultiValueMap<String, Object>(); private final MultiValueMap<String, Object> headers = new LinkedMultiValueMap<String, Object>();
@@ -116,14 +115,11 @@ public class MockHttpServletRequestBuilder
* the {@code MockHttpServletRequest} can be plugged in via * the {@code MockHttpServletRequest} can be plugged in via
* {@link #with(RequestPostProcessor)}. * {@link #with(RequestPostProcessor)}.
* @param httpMethod the HTTP method (GET, POST, etc) * @param httpMethod the HTTP method (GET, POST, etc)
* @param urlTemplate a URL template; the resulting URL will be encoded * @param url a URL template; the resulting URL will be encoded
* @param urlVariables zero or more URL variables * @param vars zero or more URL variables
*/ */
MockHttpServletRequestBuilder(HttpMethod httpMethod, String urlTemplate, Object... urlVariables) { MockHttpServletRequestBuilder(HttpMethod httpMethod, String url, Object... vars) {
Assert.notNull(httpMethod, "httpMethod is required"); this(httpMethod, UriComponentsBuilder.fromUriString(url).buildAndExpand(vars).encode().toUri());
Assert.notNull(urlTemplate, "uriTemplate is required");
this.method = httpMethod;
this.uriComponents = UriComponentsBuilder.fromUriString(urlTemplate).buildAndExpand(urlVariables).encode();
} }
/** /**
@@ -133,14 +129,14 @@ public class MockHttpServletRequestBuilder
* the {@code MockHttpServletRequest} can be plugged in via * the {@code MockHttpServletRequest} can be plugged in via
* {@link #with(RequestPostProcessor)}. * {@link #with(RequestPostProcessor)}.
* @param httpMethod the HTTP method (GET, POST, etc) * @param httpMethod the HTTP method (GET, POST, etc)
* @param uri the URL * @param url the URL
* @since 4.0.3 * @since 4.0.3
*/ */
MockHttpServletRequestBuilder(HttpMethod httpMethod, URI uri) { MockHttpServletRequestBuilder(HttpMethod httpMethod, URI url) {
Assert.notNull(httpMethod, "httpMethod is required"); Assert.notNull(httpMethod, "httpMethod is required");
Assert.notNull(uri, "uri is required"); Assert.notNull(url, "url is required");
this.method = httpMethod; this.method = httpMethod;
this.uriComponents = UriComponentsBuilder.fromUri(uri).build(); this.url = url;
} }
@@ -559,18 +555,18 @@ public class MockHttpServletRequestBuilder
public final MockHttpServletRequest buildRequest(ServletContext servletContext) { public final MockHttpServletRequest buildRequest(ServletContext servletContext) {
MockHttpServletRequest request = createServletRequest(servletContext); MockHttpServletRequest request = createServletRequest(servletContext);
String requestUri = this.uriComponents.getPath(); String requestUri = this.url.getRawPath();
request.setRequestURI(requestUri); request.setRequestURI(requestUri);
updatePathRequestProperties(request, requestUri); updatePathRequestProperties(request, requestUri);
if (this.uriComponents.getScheme() != null) { if (this.url.getScheme() != null) {
request.setScheme(this.uriComponents.getScheme()); request.setScheme(this.url.getScheme());
} }
if (this.uriComponents.getHost() != null) { if (this.url.getHost() != null) {
request.setServerName(uriComponents.getHost()); request.setServerName(this.url.getHost());
} }
if (this.uriComponents.getPort() != -1) { if (this.url.getPort() != -1) {
request.setServerPort(this.uriComponents.getPort()); request.setServerPort(this.url.getPort());
} }
request.setMethod(this.method.name()); request.setMethod(this.method.name());
@@ -582,11 +578,14 @@ public class MockHttpServletRequestBuilder
} }
try { try {
if (this.uriComponents.getQuery() != null) { if (this.url.getRawQuery() != null) {
request.setQueryString(this.uriComponents.getQuery()); request.setQueryString(this.url.getRawQuery());
} }
for (Entry<String, List<String>> entry : this.uriComponents.getQueryParams().entrySet()) { MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUri(this.url).build().getQueryParams();
for (Entry<String, List<String>> entry : queryParams.entrySet()) {
for (String value : entry.getValue()) { for (String value : entry.getValue()) {
value = (value != null) ? UriUtils.decode(value, "UTF-8") : null; value = (value != null) ? UriUtils.decode(value, "UTF-8") : null;
request.addParameter(UriUtils.decode(entry.getKey(), "UTF-8"), value); request.addParameter(UriUtils.decode(entry.getKey(), "UTF-8"), value);

View File

@@ -16,6 +16,8 @@
package org.springframework.test.web.servlet.request; package org.springframework.test.web.servlet.request;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.Principal; import java.security.Principal;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@@ -91,6 +93,16 @@ public class MockHttpServletRequestBuilderTests {
assertEquals("/foo%20bar", request.getRequestURI()); assertEquals("/foo%20bar", request.getRequestURI());
} }
// SPR-13435
@Test
public void requestUriWithDoubleSlashes() throws URISyntaxException {
this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, new URI("/test//currentlyValid/0"));
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
assertEquals("/test//currentlyValid/0", request.getRequestURI());
}
@Test @Test
public void contextPathEmpty() { public void contextPathEmpty() {
this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo"); this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo");