0

I am trying to use a curl script that works perfectly fine on both Windows and Linux in a Java program. As it is a very specific use-case, it needs to be taken from a text file and may be changed on the fly. So my goal is to create a java class that can just complete a generic curl call to a specific website using the Runtime.getRuntime().exec function.

When the code is run, it gives back "{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}". I have tried swapping single quotes for double quotes, as well as removing quotes all-together (as one answer on here said worked for them). None of those things worked. Some of them appeared to be causing the code to assume it was multiple curl calls in one and said it could not find hosts for each line in the string.

Before I go ahead and re-write everything to parse the string into the ProcessBuilder, is there something I have missed that would solve this?

The String I have been using

String tokenResults = runProcess("curl -X POST https://fakeurl/oauth/token -H \"Authorization: "
                + "Basic fakestringwithabunchofrandomcharacters1234567890123=\" "
                + "-H \"Content-Type: application/x-www-form-urlencoded\" -d grant_type=client_credentials");

The code for runProcess:

private String runProcess(String command) throws SpecialException{
    try {
        Process proc = Runtime.getRuntime().exec(command);
        InputStream resultStream = proc.getInputStream();
        InputStream errorStream = proc.getErrorStream();

        // If there was an error creating this process, print it and fail out
        if(errorStream.available() > 0) {
            BufferedReader errors = new BufferedReader(new InputStreamReader(errorStream));
            StringBuilder errorString = new StringBuilder();
            String line;
            while( (line = errors.readLine()) != null) {
                errorString.append(line);
            }
            throw new SpecialException(this.getClass().getName(), "Failed to complete the process due to the following error:\n"
                     + errorString.toString());
        }

        // Since there were no errors, read the output
        BufferedReader results = new BufferedReader(new InputStreamReader(resultStream));
        StringBuilder resultString = new StringBuilder();
        String line;
        while( (line = results.readLine()) != null) {
            resultString.append(line);
        }

        return resultString.toString();

    } catch (IOException e) {
        log("Failed to complete the process. Please check your input and try again");
        throw new SpecialException(this.getClass().getName(), "Failed to complete the process being run", e);
    }
}
KM529
  • 372
  • 4
  • 17
  • 2
    Which version of Java are you using? There are easier methods of sending a POST request, especially with `java.net.http.HttpClient` in Java 11+. – Jacob G. Nov 13 '19 at 20:27
  • We are transitioning to Java 11 soon, but at the moment this needs to be compatible with Java 7 due to this being an older server. Unfortunately I don't have the luxury of waiting until that changes. – KM529 Nov 13 '19 at 20:30
  • Gotcha. I definitely recommend looking at [Sending HTTP POST Request In Java](https://stackoverflow.com/a/3324964/7294647) then. – Jacob G. Nov 13 '19 at 20:32
  • As I mentioned above, the reason I haven't done that is the String I am taking in may have a variable number of properties and needs to be able to be changed easily. So while I could do the amount of String parsing this would take, I would prefer to avoid that given I already have a working curl String that I was provided to start with – KM529 Nov 13 '19 at 20:35
  • Instead of passing `command` into `Runtime#exec`, can you try passing `command.split("\\s+(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)")`? This will split the curl `String` by whitespace (except if in-between quotation marks), which may parse the headers differently from how they are now. - Regex taken from [here](https://stackoverflow.com/a/18893443/7294647). – Jacob G. Nov 13 '19 at 20:53
  • It changed it to a Bad Request response. I think I'm just going to switch the way this works to something more long-winded – KM529 Nov 13 '19 at 21:16
  • Of all the ways to call an external process, the single-argument Runtime.exec method is the worst. I would be surprised if the double-quotes embedded in your command worked as expected. Using ProcessBuilder is easier than you think: `new ArrayList(Arrays.asList("curl", "-X", "POST", "https://fakeurl/oauth/token", "-H", "Authorization: Basic fakestringwithabunchofrandomcharacters1234567890123=", "-H", "Content-Type: application/x-www-form-urlencoded", "-d", "grant_type=client_credentials"));` (Notice, *all* double-quotes removed.) – VGR Nov 13 '19 at 21:33

0 Answers0