Urlencode POST to conduit
Phabricator API expects POST be urlencoded, much like when a browser
submit a form (Content-Type: x-www-form-urlencoded) with the payload
being urlencoded.
As an example, when doing a `maniphest.edit` to add a comment containing
'http://example.org/r/+/1234', the content is send as is but urldecoded
by Phabricator which show with: 'http://example.org/r/ /1234', the '+'
has been decoded to a space.
We previously encountered the issue with commit message which we escapes
in the soy template: ${escapedSubject|escapeUri} which is merely a
workaround. Some support request got send previously at:
https://github.com/google/closure-templates/issues/152 which missed the
lack of urlencoding in the POST.
Instead of sending a StringEntity with 'param=<json>', use a
UrlEncodedFormEntity which takes care of encoding. Soy templates can
then drop usage of `escapeUri`.
Bug: https://phabricator.wikimedia.org/T280197
Change-Id: Icee02a62853817ecaa73403c44ce557634ecb07e
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/phabricator/conduit/ConduitConnection.java b/src/main/java/com/googlesource/gerrit/plugins/its/phabricator/conduit/ConduitConnection.java
index 8eb695b..585cd3b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/phabricator/conduit/ConduitConnection.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/phabricator/conduit/ConduitConnection.java
@@ -22,14 +22,18 @@
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.CallCapsule;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntity;
+import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/** Abstracts the connection to Conduit API */
@@ -101,7 +105,10 @@
String json = gson.toJson(params);
logger.atFinest().log("Calling phabricator method %s with the parameters %s", method, json);
- httppost.setEntity(new StringEntity("params=" + json, StandardCharsets.UTF_8));
+
+ List<NameValuePair> values = new ArrayList<NameValuePair>();
+ values.add(new BasicNameValuePair("params", json));
+ httppost.setEntity(new UrlEncodedFormEntity(values, StandardCharsets.UTF_8));
try (CloseableHttpResponse response = getClient().execute(httppost)) {
logger.atFinest().log("Phabricator HTTP response status: %s", response.getStatusLine());