Skip to content

Commit

Permalink
Revisit request parameters access with HtmlUnit
Browse files Browse the repository at this point in the history
Prior to this commit, the `HtmlUnitRequestBuilder` would "translate"
HtmlUnit web requests into Servlet requests using APIs that were not
clearly defined and meant for internal usage.

HtmlUnit 2.64.0 introduced a new `.getParameters()` API for collecting
`NameValuePair` parsed from the request URI or request body, depending
on the nature of the request. This arrangement is much more stable and
in line with HtmlUnit's expectations.

This commit uses this new API and makes HtmlUnit 2.64.0 a new minimum
requirement for using HtmlUnit integration with Spring Framework.
This also removes tests that were previously testing HtmlUnit's behavior
and using the API now marked as internal.

Closes gh-28240
  • Loading branch information
bclozel committed Sep 6, 2022
1 parent 10ade23 commit dd1e6b9
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 258 deletions.
2 changes: 1 addition & 1 deletion framework-platform/framework-platform.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ dependencies {
api("jaxen:jaxen:1.2.0")
api("junit:junit:4.13.2")
api("net.sf.jopt-simple:jopt-simple:5.0.4")
api("net.sourceforge.htmlunit:htmlunit:2.63.0")
api("net.sourceforge.htmlunit:htmlunit:2.64.0")
api("org.apache-extras.beanshell:bsh:2.0b6")
api("org.apache.activemq:activemq-broker:5.16.2")
api("org.apache.activemq:activemq-kahadb-store:5.16.2")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
Expand Down Expand Up @@ -159,7 +158,7 @@ public MockHttpServletRequest buildRequest(ServletContext servletContext) {
cookies(request);
this.webRequest.getAdditionalHeaders().forEach(request::addHeader);
locales(request);
params(request, uri);
params(request);
request.setQueryString(uri.getQuery());

return postProcess(request);
Expand Down Expand Up @@ -364,42 +363,36 @@ private void locales(MockHttpServletRequest request) {
}
}

private void params(MockHttpServletRequest request, UriComponents uriComponents) {
uriComponents.getQueryParams().forEach((name, values) -> {
String urlDecodedName = urlDecode(name);
values.forEach(value -> {
value = (value != null ? urlDecode(value) : "");
request.addParameter(urlDecodedName, value);
});
});
for (NameValuePair param : this.webRequest.getRequestParameters()) {
if (param instanceof KeyDataPair pair) {
File file = pair.getFile();
MockPart part;
if (file != null) {
part = new MockPart(pair.getName(), file.getName(), readAllBytes(file));
}
else {
// Support empty file upload OR file upload via setData().
// For an empty file upload, getValue() returns an empty string, and
// getData() returns null.
// For a file upload via setData(), getData() returns the file data, and
// getValue() returns the file name (if set) or an empty string.
part = new MockPart(pair.getName(), pair.getValue(), pair.getData());
}
MediaType mediaType = (pair.getMimeType() != null ? MediaType.valueOf(pair.getMimeType()) :
MediaType.APPLICATION_OCTET_STREAM);
part.getHeaders().setContentType(mediaType);
request.addPart(part);
private void params(MockHttpServletRequest request) {
for (NameValuePair param : this.webRequest.getParameters()) {
addRequestParameter(request, param);
}
}

private void addRequestParameter(MockHttpServletRequest request, NameValuePair param) {
if (param instanceof KeyDataPair) {
KeyDataPair pair = (KeyDataPair) param;
File file = pair.getFile();
MockPart part;
if (file != null) {
part = new MockPart(pair.getName(), file.getName(), readAllBytes(file));
}
else {
request.addParameter(param.getName(), param.getValue());
// Support empty file upload OR file upload via setData().
// For an empty file upload, getValue() returns an empty string, and
// getData() returns null.
// For a file upload via setData(), getData() returns the file data, and
// getValue() returns the file name (if set) or an empty string.
part = new MockPart(pair.getName(), pair.getValue(), pair.getData());
}
MediaType mediaType = (pair.getMimeType() != null ? MediaType.valueOf(pair.getMimeType()) :
MediaType.APPLICATION_OCTET_STREAM);
part.getHeaders().setContentType(mediaType);
request.addPart(part);
}
else {
request.addParameter(param.getName(), param.getValue());
}
}

private String urlDecode(String value) {
return URLDecoder.decode(value, StandardCharsets.UTF_8);
}

private byte[] readAllBytes(File file) {
Expand Down
Loading

0 comments on commit dd1e6b9

Please sign in to comment.