0
votes

I'm having trouble with sending an HTTP POST request with a parameter that has a value that includes a whitespace. JMeter replaces every " " and "%20" with a "+".

It seems to have something to do with the HTTP implementation as it occurs only when using HttpClient3.1 and HttpClient4. The Java implementation sends whitespaces encoded and decoded. At least according to the results tree listener.

I need to be able to use the HttpClient4 however since it seems to be the only one that I can get NTLM authorization to work. Any pointers on where to look for a resolution are appreciated.

Update: found a way to send whitespaces with the help from Richard Friedman. I ended up editing the HTTPHC4Impl.java source code which was responsible for calling the encoding.

while (args.hasNext()) {
    HTTPArgument arg = (HTTPArgument) args.next().getObjectValue();
    // The HTTPClient always urlencodes both name and value,
    // so if the argument is already encoded, we have to decode
    // it before adding it to the post request
    String parameterName = arg.getName();
    if (arg.isSkippable(parameterName)){
        continue;
    }
    String parameterValue = arg.getValue();
    if(!arg.isAlwaysEncoded()) {
        // The value is already encoded by the user
        // Must decode the value now, so that when the
        // httpclient encodes it, we end up with the same value
        // as the user had entered.
        parameterName = parameterName.replaceAll("\\+", "__tempplus__");
        parameterValue = parameterValue.replaceAll("\\+", "__tempplus__");
        parameterName = URLDecoder.decode(parameterName, urlContentEncoding);
        parameterValue = URLDecoder.decode(parameterValue, urlContentEncoding);
    }
    // Add the parameter, httpclient will urlencode it
    nvps.add(new BasicNameValuePair(parameterName, parameterValue));
}
//UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvps, urlContentEncoding);
StringBuilder asdf = new StringBuilder();
for (NameValuePair pair : nvps) {
    String name = URLEncoder.encode(pair.getName(), urlContentEncoding);
    name = name.replaceAll("\\+", "%20");
    name = name.replaceAll("__tempplus__", "%2B");
    String value = URLEncoder.encode(pair.getValue(), urlContentEncoding);
    value = value.replaceAll("\\+", "%20");
    value = value.replaceAll("__tempplus__", "%2B");
    asdf.append(name);
    asdf.append("=");
    asdf.append(value);
    asdf.append("&");
}
asdf.deleteCharAt(asdf.length()-1);
StringEntity entity = new StringEntity(asdf.toString(), urlContentEncoding);
post.setEntity(entity);

While this was quick and dirty, it did accomplish the task. Basically the plus signs are replaced to a temporary value before decoding as to not get mistaken for whitespaces. Then after encoding plus signs get converted to %20 and the temporary plus signs are encoded to %2B.

1
Do you have 'Use multipart/form-data for POST' checked? That seems to work consistently across the HTTP implementations.Richard Friedman

1 Answers

0
votes

I see the same behavior in my sample test. If you want to control if they are encoded and still use the HTTPClient you must check - 'Use multipart/form-data for POST'.

With the Java implementation during a POST you can control if parameters are encoded. However, HTTPClient will always encode the parameters for a POST which is not multipart.

This is explained in the source code for HTTPHC4Impl.java, which is the sampler for HTTP Request HTTPClient4.

    while (args.hasNext()) {
    HTTPArgument arg = (HTTPArgument) args.next().getObjectValue();
    // The HTTPClient always urlencodes both name and value,
    // so if the argument is already encoded, we have to decode
    // it before adding it to the post request
    String parameterName = arg.getName();
    if (arg.isSkippable(parameterName)){
        continue;
    }
    String parameterValue = arg.getValue();
    if(!arg.isAlwaysEncoded()) {
        // The value is already encoded by the user
        // Must decode the value now, so that when the
        // httpclient encodes it, we end up with the same value
        // as the user had entered.
        parameterName = URLDecoder.decode(parameterName, urlContentEncoding);
        parameterValue = URLDecoder.decode(parameterValue, urlContentEncoding);
    }
    // Add the parameter, httpclient will urlencode it
    nvps.add(new BasicNameValuePair(parameterName, parameterValue));
}

You can grab the JMX File from this load test.

If you pass in the data through the Body Data you can control the content and cause the data to not be encoded.

Here is an updated JMX File and Test Results with

  • One HTTP Request with Parameters, showing the issue
  • And the second request using the Body Data

You can view the Results Tree to see it passing the data without encoding. enter image description here