nick
nick

Reputation: 489

How to escape characters in a URL in a command used in child.process.exec in node

I have a working command that can be used to execute Rscript like this:

Rscript 02_Meta_Analyses.R --api_es 
http://localhost:8071/api/v1/studies/analysisData\?study\=00000000- 
0000-4000-0000-000000000000\&study\=00000000-0000-4000-0000- 
000000000001\&study\=00000000-0000-4200-0000-000000000000 --uuid 
STUDY_ID --author AUTHOR --year YEAR --type_1 GROUP1 --type_2 
GROUP2 --pedro PEDRO --api_select 
http://localhost:8071/api/v1/analysis/meta- 
analysis/5ad8505491951a966b6984fb --uuid_select STUDY_ID -- 
outbroad_select OUT_BROAD_SELECT

This script is working when I enter it directly into my shell

However, as the uuids in the arguments are dynamically generated. I create the command string and use it in the child_procee.exec(command) like this:

// create the command.
const command = 'Rscript 02_Meta_Analyses.R --api_es 
http://localhost:8071/api/v1/studies/analysisData?study\=00000000- 
0000-4000-0000-000000000000&study=00000000-0000-4000-0000- 
000000000001&study=00000000-0000-4200-0000-000000000000 --uuid 
STUDY_ID --author AUTHOR --year YEAR --type_1 GROUP1 --type_2 
GROUP2 --pedro PEDRO --api_select 
http://localhost:8071/api/v1/analysis/meta- 
analysis/5ad8505491951a966b6984fb --uuid_select STUDY_ID -- 
outbroad_select OUT_BROAD_SELECT'

// execute the command.
const { exec } = require('child_process');
  exec(command, options, (error, stdout, stderr) => {
if (error) {
  pino.info(`Metadata analysis exec error: ${error}`);
  sendFailureEmail(user.email, done);
} else {
  ........  
}

I tried everything I can do:

e.g 1

const command = 'Rscript 02_Meta_Analyses.R --api_es 
http://localhost:8071/api/v1/studies/analysisData\\?study\\=00000000- 
0000-4000-0000-000000000000\\&study\\=00000000-0000-4000-0000- 
000000000001\\&study\\=00000000-0000-4200-0000-000000000000 --uuid 
STUDY_ID --author AUTHOR --year YEAR --type_1 GROUP1 --type_2 
GROUP2 --pedro PEDRO --api_select 
http://localhost:8071/api/v1/analysis/meta- 
analysis/5ad8505491951a966b6984fb --uuid_select STUDY_ID -- 
outbroad_select OUT_BROAD_SELECT

e.g 2:

const command = 'Rscript 02_Meta_Analyses.R --api_es 
"http://localhost:8071/api/v1/studies/analysisData\\? 
study\\=00000000- 
0000-4000-0000-000000000000\\&study\\=00000000-0000-4000-0000- 
000000000001\\&study\\=00000000-0000-4200-0000-000000000000" --uuid 
STUDY_ID --author AUTHOR --year YEAR --type_1 GROUP1 --type_2 
GROUP2 --pedro PEDRO --api_select 
http://localhost:8071/api/v1/analysis/meta- 
analysis/5ad8505491951a966b6984fb --uuid_select STUDY_ID -- 
outbroad_select OUT_BROAD_SELECT'

But it seems I can't get a valid command can be used to execute the R script. Hope I clarified my problem, I would be really appreciated for any tips on this.

Upvotes: 1

Views: 240

Answers (1)

Marc Coiffier
Marc Coiffier

Reputation: 194

Sometimes, the best way to win is not to fight at all. That goes double with shell quoting.

If you write that command to a script, you can exec that script with only UUIDs as parameter, avoiding the need to escape everything. Based on your example, such a script would look like :

#!/bin/sh
Rscript 02_Meta_Analyses.R --api_es "http://localhost:8071/api/v1/studies/analysisData?study=$1&study=$2&study=$3" \
 --uuid STUDY_ID --author AUTHOR --year YEAR --type_1 GROUP1 --type_2 GROUP2 \
 --pedro PEDRO --api_select "http://localhost:8071/api/v1/analysis/meta-analysis/$4" --uuid_select STUDY_ID --outbroad_select OUT_BROAD_SELECT

If you save that file as magic-R-script, then you can build your command like so :

const command = 'sh magic-R-script <UUID1> <UUID2> <UUID3> <UUID4>'

All the quoting is then taken care of by the shell, letting you avoid your problems for one more day.

Upvotes: 1

Related Questions