Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public enum AppsmithError {
MARKETPLACE_TIMEOUT(504, 5041, "Marketplace is responding too slowly. Please try again later"),
DATASOURCE_HAS_ACTIONS(409, 4030, "Cannot delete datasource since it has {0} action(s) using it."),
ORGANIZATION_ID_NOT_GIVEN(400, 4031, "Missing organization id. Please enter one."),
INVALID_CURL_METHOD(400, 4032, "Invalid method in cURL command: {0}."),
;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.appsmith.external.models.Property;
import com.appsmith.server.domains.Action;
import com.appsmith.server.domains.Datasource;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -48,27 +49,35 @@ public CurlImporterService(ActionService actionService, PluginService pluginServ

@Override
public Mono<Action> importAction(Object input, String pageId, String name, String orgId) {
Action action = curlToAction((String) input, pageId, name);
Action action;

try {
action = curlToAction((String) input, pageId, name);
} catch (AppsmithException e) {
return Mono.error(e);
}

if (action == null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_CURL_COMMAND));
}

// Set the default values for datasource (plugin, name) and then create the action
// with embedded datasource
return pluginService.findByPackageName(RESTAPI_PLUGIN)
.flatMap(plugin -> {
final Datasource datasource = action.getDatasource();
return Mono.zip(Mono.just(action), pluginService.findByPackageName(RESTAPI_PLUGIN))
.flatMap(tuple -> {
final Action action1 = tuple.getT1();
final Plugin plugin = tuple.getT2();
final Datasource datasource = action1.getDatasource();
final DatasourceConfiguration datasourceConfiguration = datasource.getDatasourceConfiguration();
datasource.setName(datasourceConfiguration.getUrl());
datasource.setPluginId(plugin.getId());
datasource.setOrganizationId(orgId);
return Mono.just(action);
return Mono.just(action1);
})
.flatMap(actionService::create);
}

public Action curlToAction(String command, String pageId, String name) {
public Action curlToAction(String command, String pageId, String name) throws AppsmithException {
Action action = curlToAction(command);
if (action != null) {
action.setPageId(pageId);
Expand All @@ -77,7 +86,7 @@ public Action curlToAction(String command, String pageId, String name) {
return action;
}

public Action curlToAction(String command) {
public Action curlToAction(String command) throws AppsmithException {
// Three stages of parsing the cURL command:
// 1. lex: Split the string into tokens, respecting the quoting semantics of a POSIX-compliant shell.
// 2. normalize: Normalize all the command line arguments of a curl command, into their long-form versions.
Expand Down Expand Up @@ -238,7 +247,7 @@ public List<String> normalize(List<String> tokens) {
return normalizedTokens;
}

public Action parse(List<String> tokens) {
public Action parse(List<String> tokens) throws AppsmithException {
// Curl argument parsing as per <https://linux.die.net/man/1/curl>.

if (!"curl".equals(tokens.get(0))) {
Expand Down Expand Up @@ -267,7 +276,11 @@ public Action parse(List<String> tokens) {

if (ARG_REQUEST.equals(state)) {
// The `token` is next to `--request`.
actionConfiguration.setHttpMethod(HttpMethod.valueOf(token.toUpperCase()));
final HttpMethod method = HttpMethod.resolve(token.toUpperCase());
if (method == null) {
throw new AppsmithException(AppsmithError.INVALID_CURL_METHOD, token);
}
actionConfiguration.setHttpMethod(method);

} else if (ARG_HEADER.equals(state)) {
// The `token` is next to `--header`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.Page;
import com.appsmith.server.domains.User;
import com.appsmith.server.exceptions.AppsmithException;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -130,7 +131,7 @@ public void importValidCurlCommand() {
}

@Test
public void urlInSingleQuotes() {
public void urlInSingleQuotes() throws AppsmithException {
String command = "curl --location --request POST 'http://localhost:8080/scrap/api?slugifiedName=Freshdesk&ownerName=volodimir.kudriachenko'";
Action action = curlImporterService.curlToAction(command);

Expand All @@ -148,7 +149,7 @@ public void urlInSingleQuotes() {
}

@Test
public void missingMethod() {
public void missingMethod() throws AppsmithException {
String command = "curl http://localhost:8080/scrap/api";
Action action = curlImporterService.curlToAction(command);

Expand All @@ -166,7 +167,7 @@ public void missingMethod() {
}

@Test
public void multilineCommand() {
public void multilineCommand() throws AppsmithException {
String command = "curl -d '{\"message\": \"The force is strong with this one...\"}' \\\n" +
" -H \"Content-Type: application/json\" \\\n" +
" \"http://piper.net\"";
Expand All @@ -187,7 +188,7 @@ public void multilineCommand() {
}

@Test
public void testUrlEncodedData() {
public void testUrlEncodedData() throws AppsmithException {
Action action = curlImporterService.curlToAction(
"curl --data-urlencode '=all of this exactly, but url encoded ' http://loc"
);
Expand All @@ -211,7 +212,7 @@ public void testUrlEncodedData() {
}

@Test
public void chromeCurlCommands1() {
public void chromeCurlCommands1() throws AppsmithException {
Action action = curlImporterService.curlToAction(
"curl 'http://localhost:3000/applications/5ea054c531cc0f7a61af0cbe/pages/5ea054c531cc0f7a61af0cc0/edit/api' \\\n" +
" -H 'Connection: keep-alive' \\\n" +
Expand Down Expand Up @@ -276,7 +277,7 @@ public void chromeCurlCommands1() {
}

@Test
public void firefoxCurlCommands1() {
public void firefoxCurlCommands1() throws AppsmithException {
final Action action = curlImporterService.curlToAction("curl 'http://localhost:8080/api/v1/actions?applicationId=5ea054c531cc0f7a61af0cbe' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:75.0) Gecko/20100101 Firefox/75.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Origin: http://localhost:3000' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Referer: http://localhost:3000/' -H 'Cookie: SESSION=69b4b392-03b6-4e0a-a889-49ca4b8e267e'");
assertMethod(action, HttpMethod.GET);
assertUrl(action, "http://localhost:8080");
Expand All @@ -295,7 +296,7 @@ public void firefoxCurlCommands1() {
}

@Test
public void postmanExportCommands1() {
public void postmanExportCommands1() throws AppsmithException {
final Action action = curlImporterService.curlToAction(
"curl --location --request PUT 'https://release-api.appsmith.com/api/v1/users/5d81feb218e1c8217d20e13f' \\\n" +
"--header 'Content-Type: application/json' \\\n" +
Expand All @@ -319,7 +320,7 @@ public void postmanExportCommands1() {
}

@Test
public void postmanCreateDatasource() {
public void postmanCreateDatasource() throws AppsmithException {
final Action action = curlImporterService.curlToAction(
"curl --location --request POST 'https://release-api.appsmith.com/api/v1/datasources' \\\n" +
"--header 'Content-Type: application/json' \\\n" +
Expand Down Expand Up @@ -361,7 +362,7 @@ public void postmanCreateDatasource() {
}

@Test
public void postmanCreateProvider() {
public void postmanCreateProvider() throws AppsmithException {
final Action action = curlImporterService.curlToAction(
"curl --location --request POST 'https://release-api.appsmith.com/api/v1/providers' \\\n" +
"--header 'Cookie: SESSION=61ee9df5-3cab-400c-831b-9533218d8f9f' \\\n" +
Expand Down Expand Up @@ -429,7 +430,7 @@ public void postmanCreateProvider() {
}

@Test
public void parseCurlJsTestsPart1() {
public void parseCurlJsTestsPart1() throws AppsmithException {
// Tests adapted from <https://github.com/tj/parse-curl.js/blob/master/test.js>.

Action action = curlImporterService.curlToAction("curl http://api.sloths.com");
Expand Down Expand Up @@ -470,7 +471,7 @@ public void parseCurlJsTestsPart1() {
}

@Test
public void parseCurlJsTestsPart2() {
public void parseCurlJsTestsPart2() throws AppsmithException {
Action action = curlImporterService.curlToAction("curl -d \"foo=bar\" https://api.sloths.com");
assertMethod(action, HttpMethod.POST);
assertUrl(action, "https://api.sloths.com");
Expand Down Expand Up @@ -538,7 +539,7 @@ public void parseCurlJsTestsPart2() {
}

@Test
public void parseWithoutProtocol() {
public void parseWithoutProtocol() throws AppsmithException {
Action action = curlImporterService.curlToAction("curl api.sloths.com");
assertMethod(action, HttpMethod.GET);
assertUrl(action, "http://api.sloths.com");
Expand All @@ -548,7 +549,7 @@ public void parseWithoutProtocol() {
}

@Test
public void parseWithDashedUrlArgument() {
public void parseWithDashedUrlArgument() throws AppsmithException {
Action action = curlImporterService.curlToAction("curl --url http://api.sloths.com");
assertMethod(action, HttpMethod.GET);
assertUrl(action, "http://api.sloths.com");
Expand All @@ -558,7 +559,7 @@ public void parseWithDashedUrlArgument() {
}

@Test
public void parseWithDashedUrlArgument2() {
public void parseWithDashedUrlArgument2() throws AppsmithException {
Action action = curlImporterService.curlToAction("curl -X POST -d '{\"name\":\"test\",\"salary\":\"123\",\"age\":\"23\"}' --url http://dummy.restapiexample.com/api/v1/create");
assertMethod(action, HttpMethod.POST);
assertUrl(action, "http://dummy.restapiexample.com");
Expand All @@ -568,7 +569,7 @@ public void parseWithDashedUrlArgument2() {
}

@Test
public void parseWithSpacedHeader() {
public void parseWithSpacedHeader() throws AppsmithException {
Action action = curlImporterService.curlToAction("curl -H \"Accept:application/json\" http://httpbin.org/get");
assertMethod(action, HttpMethod.GET);
assertUrl(action, "http://httpbin.org");
Expand All @@ -578,7 +579,7 @@ public void parseWithSpacedHeader() {
}

@Test
public void parseCurlCommand1() {
public void parseCurlCommand1() throws AppsmithException {
Action action = curlImporterService.curlToAction("curl -i -H \"Accept: application/json\" -H \"Content-Type: application/json\" -X POST -d '{\"name\":\"test\",\"salary\":\"123\",\"age\":\"23\"}' --url http://dummy.restapiexample.com/api/v1/create");
assertMethod(action, HttpMethod.POST);
assertUrl(action, "http://dummy.restapiexample.com");
Expand Down