Skip to content

Commit

Permalink
WIP HtmlUnit#223 Sending AJAX POST Requests with x-www-form-urlencoded
Browse files Browse the repository at this point in the history
added another "default" case into the prepareRequestContext method for
POST, PATH and PUT requests. If no other condition holds and before
putting the content into the request body we now check if the encoding
of the request is "application/x-www-form-urlencoded", parse the content
and put the values into the request parameters.

Those request parameters are later used by Springs
RequestParamMethodArgumentResolver if htmlunit is running with MockMvc
under the hood. This is necessary as there is no parsing of the body
involved in Spring MockMvc.

The implementation now behaves as it would if the javascript code passed
a FormData instance as content.

This should also work when htmlunit runs on apaches http client as
HttpWebConnection will use the requestParameters for POST requests and
recreate the urlencoded form body. The HttpWebConnection was also
changed to do this for PATCH and PUT also if the encoding is
application/x-www-form-urlencoded

WIP: as I wasn't able to run all the tests yet
  • Loading branch information
thuri committed Jan 2, 2022
1 parent 7f70c14 commit 36532a5
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ private HttpUriRequest makeHttpMethod(final WebRequest webRequest, final HttpCli
// POST as well as PUT and PATCH
final HttpEntityEnclosingRequest method = (HttpEntityEnclosingRequest) httpMethod;

if (webRequest.getEncodingType() == FormEncodingType.URL_ENCODED && method instanceof HttpPost) {
if (webRequest.getEncodingType() == FormEncodingType.URL_ENCODED) {
final HttpPost postMethod = (HttpPost) method;
if (webRequest.getRequestBody() == null) {
final List<NameValuePair> pairs = webRequest.getRequestParameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import java.util.Locale;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.stream.Collectors;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
Expand All @@ -63,6 +64,7 @@
import org.apache.commons.logging.LogFactory;
import org.apache.http.NoHttpResponseException;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.utils.URLEncodedUtils;

import com.gargoylesoftware.htmlunit.AjaxController;
import com.gargoylesoftware.htmlunit.BrowserVersion;
Expand Down Expand Up @@ -893,9 +895,35 @@ else if (content instanceof URLSearchParams) {
else if (content instanceof Blob) {
((Blob) content).fillRequest(webRequest_);
}
// this should be the last else if before the default case
// because it will basically match nearly all requests
// as FormEncodingType.URL_ENCODED is the defautl encoding type
else if (webRequest_.getEncodingType() == FormEncodingType.URL_ENCODED) {

// If the encoding on the request is URL_ENCODED we don't set the body
// but instead parse the content and add the single request params
// to the requestParameters list
// this is necessary for cases when htmlunit is used with Springs MockMvc under the hood
// as there won't be any parsing of the content
// in case of the real http client (as in com.gargoylesoftware.htmlunit.HttpWebConnection)
// the parameters will be encoded again and put into the body
// this should fix https://github.com/HtmlUnit/htmlunit/issues/223
final String body = Context.toString(content);

if(LOG.isDebugEnabled()) {
LOG.debug("Setting request params from content "+ body);
}

webRequest_.setRequestParameters(
URLEncodedUtils
.parse(body, UTF_8).stream()
.map(nvp -> new NameValuePair(nvp.getName(), nvp.getValue()))
.collect(Collectors.toList()));
}
else {
final String body = Context.toString(content);
if (!body.isEmpty()) {

if (LOG.isDebugEnabled()) {
LOG.debug("Setting request body to: " + body);
}
Expand Down

0 comments on commit 36532a5

Please sign in to comment.