Search code examples
perlservicenow

Calling REST API with special characters in data parameters from Perl is failing


From perl i'm trying to call a servicenow rest api to update some data attributes.

I'm using curl command to achieve this and for some reasons i can't use any of the perl modules available.

I'm able to achieve this successfully without any special characters in the value field of the json.

Following is the code used for formatting the cmd:

my $comments = "b'c";
my $cmd = `curl \"$url\" -i -s --insecure --user test:test --request PUT --header "Accept:application/json" --header "Content-Type:application/json"  --data '{\"comments\":\"$comments\"}'`;

If the above value is "bc" i'm able to get the data, but if i give "b'c" the i'm getting following errors:

sh: -c: line 0: unexpected EOF while looking for matching `"'

sh: -c: line 1: syntax error: unexpected end of file

Even i tried the following code:

my $cmd = system "curl https://test.service-now.com/api/now/table/incident/code?sysparm_display_value=true -i -s --insecure --request PUT --header \"Accept:application/json\" --header \"Content-Type:application/json\"  --data '{\"comments\":\"bc\"}' --user test:test";

If a string with single quote b'c is given I'm getting the same error.

Could somebody please tell me how to handle single quote inside double quoted string?


Solution

  • I can get this working with

    my $comments = "b\"'\"c";
    

    The string that gets passed to the shell is then

    --data '{"comments":"b'"'"'c"}'
    

    which is three separate tokens concatenated together:

    '{"comments":"b'       resolves to    {"comments":"b
    "'"                    resolves to    '
    'c"}'                  resolves to    c"}
    

    Also see String::ShellQuote, which is a godsend for problems like this.

    use String::ShellQuote;
    $comments = "b'c";
    @cmd = ("curl", $URL, "-i", "-s", "--insecure", "--request",
            "PUT", "--header", "Accept:applicatin/json", "--header",
            "Content-Type:application/json",
            "--data", qq[{"comments":$comments}], "--user", "test:test");
    $cmd = shell_quote(@cmd);
    print $cmd;
    

    Gives you:

    curl 'https://test.service-now.com/api/now/table/incident/code?sysparm_display_value=true' 
        -i -s --insecure --request PUT --header 
        Accept:application/json --header Content-Type:application/json 
        --data '{"comments":"b'\''c"}' --user test:test
    

    which would also satisfy the shell's syntax checker.