[TEST] Work around URI encode limitations in RestClient

We've been relying on URI for url encoding, but it turns out it has some problems. For instance '+' stays as is while it should be encoded to `%2B`. If we go and manually encode query params we have to be careful though not to run into double encoding ('+'=>'%2B'=>'%252B'). The applied solution relies on URI encoding for the url path, but manual url encoding for the query parameters. We prevent URI from double encoding query params by using its single argument constructor that leaves everything as is.

We can also revert back the expression script REST test that revealed this to its original content (which contains an addition).

Closes #9769
Closes #9946
This commit is contained in:
javanna 2015-03-02 14:58:36 +01:00 committed by Luca Cavanna
parent 430b091e7d
commit 4ad33c30ac
2 changed files with 22 additions and 13 deletions

View File

@ -22,6 +22,6 @@ setup:
---
"Expressions scripting test":
- do: { search: { body: { script_fields : { my_field : { lang: expression, script: 'doc["age"].value' } } } } }
- match: { hits.hits.0.fields.my_field.0: 23.0 }
- do: { search: { body: { script_fields : { my_field : { lang: expression, script: 'doc["age"].value + 19' } } } } }
- match: { hits.hits.0.fields.my_field.0: 42.0 }

View File

@ -31,8 +31,10 @@ import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Map;
@ -89,8 +91,13 @@ public class HttpRequestBuilder {
}
public HttpRequestBuilder addParam(String name, String value) {
this.params.put(name, value);
try {
//manually url encode params, since URI does it only partially (e.g. '+' stays as is)
this.params.put(name, URLEncoder.encode(value, "utf-8"));
return this;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public HttpRequestBuilder addHeaders(Headers headers) {
@ -173,16 +180,18 @@ public class HttpRequestBuilder {
}
private URI buildUri() {
String query;
if (params.size() == 0) {
query = null;
} else {
query = Joiner.on('&').withKeyValueSeparator("=").join(params);
}
try {
return new URI(protocol, null, host, port, path, query, null);
//url encode rules for path and query params are different. We use URI to encode the path, but we manually encode each query param through URLEncoder.
URI uri = new URI(protocol, null, host, port, path, null, null);
//String concatenation FTW. If we use the nicer multi argument URI constructor query parameters will get only partially encoded
//(e.g. '+' will stay as is) hence when trying to properly encode params manually they will end up double encoded (+ becomes %252B instead of %2B).
StringBuilder uriBuilder = new StringBuilder(protocol).append("://").append(host).append(":").append(port).append(uri.getRawPath());
if (params.size() > 0) {
uriBuilder.append("?").append(Joiner.on('&').withKeyValueSeparator("=").join(params));
}
return URI.create(uriBuilder.toString());
} catch(URISyntaxException e) {
throw new IllegalArgumentException(e);
throw new IllegalArgumentException("unable to build uri", e);
}
}