diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java index 771e8c542a..4fdaa22a04 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java @@ -105,8 +105,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { String httpMethod = this.webRequest.getHttpMethod().name(); UriComponents uriComponents = uriComponents(); - MockHttpServletRequest request = new HtmlUnitMockHttpServletRequest(servletContext, httpMethod, - uriComponents.getPath()); + MockHttpServletRequest request = new HtmlUnitMockHttpServletRequest( + servletContext, httpMethod, uriComponents.getPath()); parent(request, this.parentBuilder); request.setServerName(uriComponents.getHost()); // needs to be first for additional headers authType(request); @@ -123,7 +123,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { request.setProtocol("HTTP/1.1"); request.setQueryString(uriComponents.getQuery()); request.setScheme(uriComponents.getScheme()); - pathInfo(uriComponents,request); + request.setPathInfo(null); return postProcess(request); } @@ -223,14 +223,14 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { try { request.setContent(requestBody.getBytes(charset)); } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); + catch (UnsupportedEncodingException ex) { + throw new IllegalStateException(ex); } } private void contentType(MockHttpServletRequest request) { String contentType = header("Content-Type"); - request.setContentType(contentType == null ? MediaType.ALL_VALUE.toString() : contentType); + request.setContentType(contentType != null ? contentType : MediaType.ALL_VALUE); } private void contextPath(MockHttpServletRequest request, UriComponents uriComponents) { @@ -245,8 +245,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } else { if (!uriComponents.getPath().startsWith(this.contextPath)) { - throw new IllegalArgumentException(uriComponents.getPath() + " should start with contextPath " - + this.contextPath); + throw new IllegalArgumentException(uriComponents.getPath() + " should start with contextPath " + + this.contextPath); } request.setContextPath(this.contextPath); } @@ -360,14 +360,10 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { private void params(MockHttpServletRequest request, UriComponents uriComponents) { for (Entry> entry : uriComponents.getQueryParams().entrySet()) { String name = entry.getKey(); + String urlDecodedName = urlDecode(name); for (String value : entry.getValue()) { - try { - value = (value != null ? URLDecoder.decode(value, "UTF-8") : ""); - request.addParameter(name, value); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + value = (value != null ? urlDecode(value) : ""); + request.addParameter(urlDecodedName, value); } } for (NameValuePair param : this.webRequest.getRequestParameters()) { @@ -375,6 +371,15 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } } + private String urlDecode(String value) { + try { + return URLDecoder.decode(value, "UTF-8"); + } + catch (UnsupportedEncodingException ex) { + throw new IllegalStateException(ex); + } + } + private Locale parseLocale(String locale) { Matcher matcher = LOCALE_PATTERN.matcher(locale); if (!matcher.matches()) { @@ -392,10 +397,6 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { return new Locale(language, country, qualifier); } - private void pathInfo(UriComponents uriComponents, MockHttpServletRequest request) { - request.setPathInfo(null); - } - private void servletPath(MockHttpServletRequest request, String requestPath) { String servletPath = requestPath.substring(request.getContextPath().length()); if ("".equals(servletPath)) { @@ -426,8 +427,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { private UriComponents uriComponents() { URL url = this.webRequest.getUrl(); - UriComponentsBuilder uriBldr = UriComponentsBuilder.fromUriString(url.toExternalForm()); - return uriBldr.build(); + return UriComponentsBuilder.fromUriString(url.toExternalForm()).build(); } @Override @@ -450,14 +450,18 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { return this; } + private CookieManager getCookieManager() { + return this.webClient.getCookieManager(); + } + /** - * An extension to {@link MockHttpServletRequest} that ensures that - * when a new {@link HttpSession} is created, it is added to the managed sessions. + * An extension to {@link MockHttpServletRequest} that ensures that when a + * new {@link HttpSession} is created, it is added to the managed sessions. */ private final class HtmlUnitMockHttpServletRequest extends MockHttpServletRequest { - private HtmlUnitMockHttpServletRequest(ServletContext servletContext, String method, String requestURI) { + public HtmlUnitMockHttpServletRequest(ServletContext servletContext, String method, String requestURI) { super(servletContext, method, requestURI); } @@ -486,16 +490,17 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } } + /** * An extension to {@link MockHttpSession} that ensures when - * {@link #invalidate()} is called that the {@link HttpSession} is - * removed from the managed sessions. + * {@link #invalidate()} is called that the {@link HttpSession} + * is removed from the managed sessions. */ private final class HtmlUnitMockHttpSession extends MockHttpSession { private final MockHttpServletRequest request; - private HtmlUnitMockHttpSession(MockHttpServletRequest request) { + public HtmlUnitMockHttpSession(MockHttpServletRequest request) { super(request.getServletContext()); this.request = request; } @@ -514,8 +519,4 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } } - private CookieManager getCookieManager() { - return this.webClient.getCookieManager(); - } - } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java index b579ea813d..ddf6830640 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet.htmlunit; +import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; @@ -27,9 +28,11 @@ import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; -import org.apache.commons.io.IOUtils; +import com.gargoylesoftware.htmlunit.HttpMethod; +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.WebRequest; +import com.gargoylesoftware.htmlunit.util.NameValuePair; import org.apache.http.auth.UsernamePasswordCredentials; - import org.junit.Before; import org.junit.Test; @@ -39,16 +42,12 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.FileCopyUtils; -import com.gargoylesoftware.htmlunit.HttpMethod; -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.WebRequest; -import com.gargoylesoftware.htmlunit.util.NameValuePair; - -import static java.util.Arrays.asList; +import static java.util.Arrays.*; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.junit.Assert.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; /** * Unit tests for {@link HtmlUnitRequestBuilder}. @@ -77,7 +76,6 @@ public class HtmlUnitRequestBuilderTests { requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest); } - // --- constructor @Test(expected = IllegalArgumentException.class) public void constructorNullSessions() { @@ -94,8 +92,6 @@ public class HtmlUnitRequestBuilderTests { new HtmlUnitRequestBuilder(sessions, webClient, null); } - // --- buildRequest - @Test @SuppressWarnings("deprecation") public void buildRequestBasicAuth() { @@ -245,7 +241,8 @@ public class HtmlUnitRequestBuilderTests { MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); - assertThat(IOUtils.toString(actualRequest.getInputStream()), equalTo(content)); + assertThat(FileCopyUtils.copyToString(new InputStreamReader(actualRequest.getInputStream(), "ISO-8859-1")), + equalTo(content)); } @Test @@ -411,6 +408,26 @@ public class HtmlUnitRequestBuilderTests { assertThat(actualRequest.getParameter("name"), equalTo("value")); } + @Test // SPR-14177 + public void buildRequestParameterMapDecodesParameterName() throws Exception { + webRequest.setUrl(new URL("http://example.com/example/?row%5B0%5D=value")); + + MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); + + assertThat(actualRequest.getParameterMap().size(), equalTo(1)); + assertThat(actualRequest.getParameter("row[0]"), equalTo("value")); + } + + @Test + public void buildRequestParameterMapDecodesParameterValue() throws Exception { + webRequest.setUrl(new URL("http://example.com/example/?name=row%5B0%5D")); + + MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); + + assertThat(actualRequest.getParameterMap().size(), equalTo(1)); + assertThat(actualRequest.getParameter("name"), equalTo("row[0]")); + } + @Test public void buildRequestParameterMapFromSingleQueryParamWithoutValueAndWithoutEqualsSign() throws Exception { webRequest.setUrl(new URL("http://example.com/example/?name")); @@ -544,7 +561,7 @@ public class HtmlUnitRequestBuilderTests { MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); - assertThat(IOUtils.toString(actualRequest.getReader()), equalTo(expectedBody)); + assertThat(FileCopyUtils.copyToString(actualRequest.getReader()), equalTo(expectedBody)); } @Test