From e15ed44a68a9d4847dcf1a424d0557b3e00e7ce1 Mon Sep 17 00:00:00 2001 From: Evgenii Koba Date: Sat, 18 Apr 2020 14:48:01 +1000 Subject: [PATCH 1/2] Make HtmlUnitRequestBuilder handle form data file properly See gh-18551 --- .../htmlunit/HtmlUnitRequestBuilder.java | 25 ++++++++++++++++++- .../htmlunit/HtmlUnitRequestBuilderTests.java | 22 ++++++++++++++++ .../test/web/htmlunit/test.txt | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 spring-test/src/test/resources/org/springframework/test/web/htmlunit/test.txt 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 6308d61603..3b06ed3dbc 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 @@ -16,11 +16,14 @@ package org.springframework.test.web.servlet.htmlunit; +import java.io.File; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; @@ -39,6 +42,7 @@ import com.gargoylesoftware.htmlunit.CookieManager; import com.gargoylesoftware.htmlunit.FormEncodingType; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebRequest; +import com.gargoylesoftware.htmlunit.util.KeyDataPair; import com.gargoylesoftware.htmlunit.util.NameValuePair; import org.springframework.beans.Mergeable; @@ -46,6 +50,7 @@ import org.springframework.http.MediaType; import org.springframework.lang.Nullable; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; +import org.springframework.mock.web.MockPart; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.SmartRequestBuilder; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -365,7 +370,16 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { }); }); for (NameValuePair param : this.webRequest.getRequestParameters()) { - request.addParameter(param.getName(), param.getValue()); + if (param instanceof KeyDataPair) { + KeyDataPair fileParam = (KeyDataPair) param; + File file = fileParam.getFile(); + MockPart part = new MockPart(fileParam.getName(), file.getName(), readAllBytes(file)); + part.getHeaders().setContentType(MediaType.valueOf(fileParam.getMimeType())); + request.addPart(part); + } + else { + request.addParameter(param.getName(), param.getValue()); + } } } @@ -378,6 +392,15 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } } + private byte[] readAllBytes(File file) { + try { + return Files.readAllBytes(file.toPath()); + } + catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + private void servletPath(MockHttpServletRequest request, String requestPath) { String servletPath = requestPath.substring(request.getContextPath().length()); request.setServletPath(servletPath); 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 d9711e0a98..6afbfa102f 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 @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet.htmlunit; +import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -28,17 +29,21 @@ import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; +import javax.servlet.http.Part; import com.gargoylesoftware.htmlunit.FormEncodingType; import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebRequest; +import com.gargoylesoftware.htmlunit.util.KeyDataPair; +import com.gargoylesoftware.htmlunit.util.MimeType; import com.gargoylesoftware.htmlunit.util.NameValuePair; import org.apache.commons.io.IOUtils; import org.apache.http.auth.UsernamePasswordCredentials; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.core.io.ClassPathResource; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockServletContext; @@ -418,6 +423,23 @@ public class HtmlUnitRequestBuilderTests { assertThat(actualRequest.getParameter("name2")).isEqualTo("value2"); } + @Test + public void buildRequestParameterMapViaWebRequestDotSetFileToUploadAsParameter() throws Exception { + File fileToUpload = new ClassPathResource("org/springframework/test/web/htmlunit/test.txt").getFile(); + webRequest.setRequestParameters(Arrays.asList(new KeyDataPair( + "key", fileToUpload, "test.txt", MimeType.TEXT_PLAIN, StandardCharsets.UTF_8))); + + MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); + + assertThat(actualRequest.getParts().size()).isEqualTo(1); + Part part = actualRequest.getPart("key"); + assertThat(part).isNotNull(); + assertThat(part.getName()).isEqualTo("key"); + assertThat(IOUtils.toString(part.getInputStream(), StandardCharsets.UTF_8)).isEqualTo("test file"); + assertThat(part.getSubmittedFileName()).isEqualTo("test.txt"); + assertThat(part.getContentType()).isEqualTo(MimeType.TEXT_PLAIN); + } + @Test public void buildRequestParameterMapFromSingleQueryParam() throws Exception { webRequest.setUrl(new URL("https://example.com/example/?name=value")); diff --git a/spring-test/src/test/resources/org/springframework/test/web/htmlunit/test.txt b/spring-test/src/test/resources/org/springframework/test/web/htmlunit/test.txt new file mode 100644 index 0000000000..bdf08de0f3 --- /dev/null +++ b/spring-test/src/test/resources/org/springframework/test/web/htmlunit/test.txt @@ -0,0 +1 @@ +test file \ No newline at end of file From 5883ea2721e44b2d311a03ea6f40e0ccc4573929 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 6 May 2020 09:24:39 +0100 Subject: [PATCH 2/2] Polishing contribution See gh-24926 --- .../servlet/htmlunit/HtmlUnitRequestBuilder.java | 12 ++++++------ .../htmlunit/HtmlUnitRequestBuilderTests.java | 13 +++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) 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 3b06ed3dbc..99a30e1cee 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 @@ -120,8 +120,9 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { UriComponents uriComponents = uriComponents(); String path = uriComponents.getPath(); - MockHttpServletRequest request = new HtmlUnitMockHttpServletRequest( - servletContext, httpMethod, (path != null ? path : "")); + MockHttpServletRequest request = + new HtmlUnitMockHttpServletRequest(servletContext, httpMethod, (path != null ? path : "")); + parent(request, this.parentBuilder); String host = uriComponents.getHost(); request.setServerName(host != null ? host : ""); // needs to be first for additional headers @@ -371,10 +372,9 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { }); for (NameValuePair param : this.webRequest.getRequestParameters()) { if (param instanceof KeyDataPair) { - KeyDataPair fileParam = (KeyDataPair) param; - File file = fileParam.getFile(); - MockPart part = new MockPart(fileParam.getName(), file.getName(), readAllBytes(file)); - part.getHeaders().setContentType(MediaType.valueOf(fileParam.getMimeType())); + KeyDataPair pair = (KeyDataPair) param; + MockPart part = new MockPart(pair.getName(), pair.getFile().getName(), readAllBytes(pair.getFile())); + part.getHeaders().setContentType(MediaType.valueOf(pair.getMimeType())); request.addPart(part); } else { 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 6afbfa102f..ad84f9ad89 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-2019 the original author or authors. + * Copyright 2002-2020 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,7 +16,6 @@ package org.springframework.test.web.servlet.htmlunit; -import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -423,11 +422,13 @@ public class HtmlUnitRequestBuilderTests { assertThat(actualRequest.getParameter("name2")).isEqualTo("value2"); } - @Test + @Test // gh-24926 public void buildRequestParameterMapViaWebRequestDotSetFileToUploadAsParameter() throws Exception { - File fileToUpload = new ClassPathResource("org/springframework/test/web/htmlunit/test.txt").getFile(); - webRequest.setRequestParameters(Arrays.asList(new KeyDataPair( - "key", fileToUpload, "test.txt", MimeType.TEXT_PLAIN, StandardCharsets.UTF_8))); + + webRequest.setRequestParameters(Collections.singletonList( + new KeyDataPair("key", + new ClassPathResource("org/springframework/test/web/htmlunit/test.txt").getFile(), + "test.txt", MimeType.TEXT_PLAIN, StandardCharsets.UTF_8))); MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext);