Skip to content

Commit

Permalink
Enable toggle for params encoding (#2968)
Browse files Browse the repository at this point in the history
Enable toggle for params encoding
1. Add toggle param to ActionConfiguration class.
2. Add TCs to test toggle on/off/null.
  • Loading branch information
sumitsum committed Feb 11, 2021
1 parent 0da3421 commit e9e30d1
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class ActionConfiguration {
// API fields
String path;
List<Property> headers;
Boolean encodeParamsToggle;
List<Property> queryParameters;
String body;
// For form-data input instead of json use the following
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,23 @@ public Mono<ActionExecutionResult> execute(APIConnection apiConnection,
String url = datasourceConfiguration.getUrl() + path;
String reqContentType = "";

/*
* - If encodeParamsToggle is null, then assume it to be true because params are supposed to be
* encoded by default, unless explicitly prohibited by the user.
*/
Boolean encodeParamsToggle = true;
if(actionConfiguration.getEncodeParamsToggle() != null
&& actionConfiguration.getEncodeParamsToggle() == false) {
encodeParamsToggle = false;
}

HttpMethod httpMethod = actionConfiguration.getHttpMethod();
URI uri;
try {
String httpUrl = addHttpToUrlWhenPrefixNotPresent(url);
uri = createFinalUriWithQueryParams(httpUrl, actionConfiguration.getQueryParameters());
uri = createFinalUriWithQueryParams(httpUrl,
actionConfiguration.getQueryParameters(),
encodeParamsToggle);
} catch (URISyntaxException e) {
ActionExecutionRequest actionExecutionRequest = populateRequestFields(actionConfiguration, null);
actionExecutionRequest.setUrl(url);
Expand Down Expand Up @@ -141,7 +153,9 @@ public Mono<ActionExecutionResult> execute(APIConnection apiConnection,

if (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(reqContentType)
|| MediaType.MULTIPART_FORM_DATA_VALUE.equals(reqContentType)) {
requestBodyAsString = convertPropertyListToReqBody(actionConfiguration.getBodyFormData(), reqContentType);
requestBodyAsString = convertPropertyListToReqBody(actionConfiguration.getBodyFormData(),
reqContentType,
encodeParamsToggle);
}

// If users have chosen to share the Appsmith signature in the header, calculate and add that
Expand Down Expand Up @@ -287,7 +301,9 @@ private String getSignatureKey(DatasourceConfiguration datasourceConfiguration)
return null;
}

public String convertPropertyListToReqBody(List<Property> bodyFormData, String reqContentType) {
public String convertPropertyListToReqBody(List<Property> bodyFormData,
String reqContentType,
Boolean encodeParamsToggle) {
if (bodyFormData == null || bodyFormData.isEmpty()) {
return "";
}
Expand All @@ -297,7 +313,8 @@ public String convertPropertyListToReqBody(List<Property> bodyFormData, String r
String key = property.getKey();
String value = property.getValue();

if (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(reqContentType)) {
if (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(reqContentType)
&& encodeParamsToggle == true) {
try {
value = URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
Expand Down Expand Up @@ -501,16 +518,28 @@ private String addHttpToUrlWhenPrefixNotPresent(String url) {
return "http://" + url;
}

private URI createFinalUriWithQueryParams(String url, List<Property> queryParams) throws URISyntaxException {
private URI createFinalUriWithQueryParams(String url,
List<Property> queryParams,
Boolean encodeParamsToggle) throws URISyntaxException {
UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance();
uriBuilder.uri(new URI(url));

if (queryParams != null) {
for (Property queryParam : queryParams) {
String key = queryParam.getKey();
if (StringUtils.isNotEmpty(key)) {
uriBuilder.queryParam(URLEncoder.encode(key, StandardCharsets.UTF_8),
URLEncoder.encode(queryParam.getValue(), StandardCharsets.UTF_8));
if(encodeParamsToggle == true) {
uriBuilder.queryParam(
URLEncoder.encode(key, StandardCharsets.UTF_8),
URLEncoder.encode(queryParam.getValue(), StandardCharsets.UTF_8)
);
}
else {
uriBuilder.queryParam(
key,
queryParam.getValue()
);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import reactor.core.Exceptions;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.crypto.SecretKey;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
Expand All @@ -47,7 +48,6 @@ public void testValidJsonApiExecution() {
actionConfig.setBody(requestBody);

Mono<ActionExecutionResult> resultMono = pluginExecutor.execute(null, dsConfig, actionConfig);

StepVerifier.create(resultMono)
.assertNext(result -> {
assertTrue(result.getIsExecutionSuccess());
Expand All @@ -59,9 +59,10 @@ public void testValidJsonApiExecution() {
}

@Test
public void testEncodingFunction() throws UnsupportedEncodingException {
public void testEncodingFunctionWithEncodeParamsToggleTrue() throws UnsupportedEncodingException {
String encoded_value = pluginExecutor.convertPropertyListToReqBody(List.of(new Property("key", "valüe")),
"application/x-www-form-urlencoded");
"application/x-www-form-urlencoded",
true);
String expected_value = null;
try {
expected_value = "key=" + URLEncoder.encode("valüe", StandardCharsets.UTF_8.toString());
Expand All @@ -71,6 +72,20 @@ public void testEncodingFunction() throws UnsupportedEncodingException {
assertEquals(expected_value, encoded_value);
}

@Test
public void testEncodingFunctionWithEncodeParamsToggleFalse() throws UnsupportedEncodingException {
String encoded_value = pluginExecutor.convertPropertyListToReqBody(List.of(new Property("key", "valüe")),
"application/x-www-form-urlencoded",
false);
String expected_value = null;
try {
expected_value = "key=" + URLEncoder.encode("valüe", StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
throw e;
}
assertNotEquals(expected_value, encoded_value);
}

@Test
public void testValidFormApiExecution() {
DatasourceConfiguration dsConfig = new DatasourceConfiguration();
Expand Down Expand Up @@ -174,4 +189,91 @@ public void testInvalidSignature() {
})
.verifyComplete();
}

@Test
public void testEncodeParamsToggleOn() {
DatasourceConfiguration dsConfig = new DatasourceConfiguration();
dsConfig.setUrl("https://postman-echo.com/post");

ActionConfiguration actionConfig = new ActionConfiguration();
actionConfig.setHeaders(List.of(new Property("content-type", "application/json")));
actionConfig.setHttpMethod(HttpMethod.POST);
String requestBody = "body";
actionConfig.setBody(requestBody);

List<Property> queryParams = new ArrayList<>();
queryParams.add(new Property("query_key", "query val")); /* encoding changes 'query val' to 'query+val' */
actionConfig.setQueryParameters(queryParams);
actionConfig.setEncodeParamsToggle(true);

Mono<ActionExecutionResult> resultMono = pluginExecutor.execute(null, dsConfig, actionConfig);

StepVerifier.create(resultMono)
.assertNext(result -> {
assertTrue(result.getIsExecutionSuccess());
assertNotNull(result.getBody());

String expected_url = "\"https://postman-echo.com/post?query_key=query+val\"";
JsonNode url = ((ObjectNode) result.getBody()).get("url");
assertEquals(expected_url, url.toString());
})
.verifyComplete();
}

@Test
public void testEncodeParamsToggleNull() {
DatasourceConfiguration dsConfig = new DatasourceConfiguration();
dsConfig.setUrl("https://postman-echo.com/post");

ActionConfiguration actionConfig = new ActionConfiguration();
actionConfig.setHeaders(List.of(new Property("content-type", "application/json")));
actionConfig.setHttpMethod(HttpMethod.POST);
String requestBody = "body";
actionConfig.setBody(requestBody);

List<Property> queryParams = new ArrayList<>();
queryParams.add(new Property("query_key", "query val")); /* encoding changes 'query val' to 'query+val' */
actionConfig.setQueryParameters(queryParams);
actionConfig.setEncodeParamsToggle(null);

Mono<ActionExecutionResult> resultMono = pluginExecutor.execute(null, dsConfig, actionConfig);

StepVerifier.create(resultMono)
.assertNext(result -> {
assertTrue(result.getIsExecutionSuccess());
assertNotNull(result.getBody());

String expected_url = "\"https://postman-echo.com/post?query_key=query+val\"";
JsonNode url = ((ObjectNode) result.getBody()).get("url");
assertEquals(expected_url, url.toString());
})
.verifyComplete();
}

@Test
public void testEncodeParamsToggleOff() {
DatasourceConfiguration dsConfig = new DatasourceConfiguration();
dsConfig.setUrl("https://postman-echo.com/post");

ActionConfiguration actionConfig = new ActionConfiguration();
actionConfig.setHeaders(List.of(new Property("content-type", "application/json")));
actionConfig.setHttpMethod(HttpMethod.POST);
String requestBody = "body";
actionConfig.setBody(requestBody);

List<Property> queryParams = new ArrayList<>();
queryParams.add(new Property("query_key", "query val"));
actionConfig.setQueryParameters(queryParams);
actionConfig.setEncodeParamsToggle(false);

Mono<RestApiPlugin.RestApiPluginExecutor> pluginExecutorMono = Mono.just(pluginExecutor);
Mono<ActionExecutionResult> resultMono = pluginExecutorMono.flatMap(executor -> executor.execute(null,
dsConfig,
actionConfig));
StepVerifier.create(resultMono)
.verifyErrorSatisfies(e -> {
assertTrue(e instanceof IllegalArgumentException);
assertTrue(e.getMessage().contains("Invalid character ' ' for QUERY_PARAM in \"query val\""));
});
}
}

0 comments on commit e9e30d1

Please sign in to comment.