Mindaugas Bernatavičius
Mindaugas Bernatavičius

Reputation: 3909

BASH: passing curl parameters as $1 variable

I have a bash script with the following function:

function curl_the_URL_and_check_status(){

   status=$(curl $1 | grep "X-Cache-Status:" | cut -d " " -f 2)

   if [[ "$status" != *"MISS"* ]]; then
       echo "
   cURL returned non MISS status. Something is not correct. Exiting with status 1
   check the status by entering curl $1"
       exit 1
   fi
}

Passing the parameters:

## My comment :: .... some more output ....
+++ grep -o -P '(?<=\/\/).*?(?=\/)'
++ host=php-mindaugasb.c9.io
+++ echo http://php-mindaugasb.c9.io/Testing/JS/displayName.js
+++ perl -pe 's|(?<=://).+?(?=/)|localhost:805|'
++ modified_URL=http://localhost:805/Testing/JS/displayName.js

## My comment ::  below is the parameter passed to the function as $1
++ cURL_string='-H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js'

I get this passed to curl:

++ echo -H '"Host:' 'php-mindaugasb.c9.io"' -I -s http://localhost:805/Testing/JS/displayName.js

Which does not work trying from console (gateway timeout error is thrown).

So my curl looks like this:

curl -H '"Host:' 'php-mindaugasb.c9.io"' -I -s http://localhost:805/Testing/JS/displayName.js

I need it to look like this (which works when tested from console):

curl -H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js

How do I make this happen?

Tried with `curl $1`, curl "$1" ...

Thanks

ADDENDUM

I call the function like this:

 # another function that constructs correct CURL string
 cURL_string="\"-H Host: $host\" -I -s $modified_URL"

 # global scope - this is where the curl is called
 curl_params=$(get_prepared_string_for_cURL $1)
 curl_the_URL_and_check_status $curl_params

(UPDATE: 14 01 2015)

Here is what I get using array approach:

cURL_string=(-H \"Host: $host\" -I -s $modified_URL)

CASES:

curl "${curl_params[@]}" ==> curl '-H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js'

curl: no URL specified!

curl ${curl_params[@]} ==> curl -H '"Host:' 'php-mindaugasb.c9.io"' -I -s http://localhost:805/Testing/JS/displayName.js

I need

curl -H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js

get_prepared_string_for_cURL

function get_prepared_string_for_cURL(){

    # get the host from URL, to use with in curl with the --Host flag
    host=$(echo $1 | grep -o -P '(?<=\/\/).*?(?=\/)')

    # replace the host part with the "localhost:805" to request the resource
    # from the nginx virtual host (server block) dedicated for proxy cache
    modified_URL=$(echo $1 | perl -pe 's|(?<=://).+?(?=/)|localhost:805|')

    # construct cURL string
    cURL_string=(-H Host: $host -I -s $modified_URL)

    # echo "$cURL_string"

    echo "${cURL_string[@]}"
}

Upvotes: 2

Views: 4072

Answers (2)

Gordon Davisson
Gordon Davisson

Reputation: 125788

The shell parses quotes before substituting variable references (e.g. $1), so if there are quotes in the value of $1, by the time they're in place it's too late for them to do anything useful. Rather than passing the curl arguments as a single argument with quotes embedded, pass it as a series of arguments and use "$@" to expand it:

function curl_the_URL_and_check_status(){

   status=$(curl "$@" | grep "X-Cache-Status:" | cut -d " " -f 2)
[...]

...and then call it with something like:

curl_the_URL_and_check_status -H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js

instead of:

curl_the_URL_and_check_status '-H "Host: php-mindaugasb.c9.io" -I -s http://localhost:805/Testing/JS/displayName.js'

But it looks like you're also building the parameter list in a variable, which causes exactly the same problem -- there's no good way to take a plain variable and split it into arguments based on embedded quotes. Again, there's a solution: use an array, with each argument being an element of the array. Then, reference the array as "${arrayname[@]}" so each element gets treated as a separate argument.

cURL_args=(-H "Host: php-mindaugasb.c9.io" -I -s "$modified_URL")
curl_the_URL_and_check_status "${cURL_args[@]}"

Upvotes: 4

Marc Bredt
Marc Bredt

Reputation: 955

you could use eval to interpret variables in a command string first and then execute it

UPDATE:

eval [arg ...]
          The args are read and concatenated together into a single command.  This command is then read and  exe‐
          cuted  by  the  shell,  and its exit status is returned as the value of eval.  If there are no args, or
          only null arguments, eval returns 0.

so you could build a command string like command="curl -H \"Content-Type: whatever\" $1 $2" afterwards run

eval ${command}

eval will read and interpret all your quotations, escapes and variables first and then run the interpreted command. hope this helps. greets.

Upvotes: 0

Related Questions