Home > Blockchain >  Variable in command substitution is expanded into multiple arguments
Variable in command substitution is expanded into multiple arguments

Time:11-13

I have tried to create a method in a bash script which should be able to perform a curl operation with a variable number of headers, however I seem to get stuck in that the curl command consider the header arguments to be multiple arguments as they contain spaces.

When I run the following line in bash I get a 201 response:

response=$($executable -X POST localhost:9200/index-template/globalmetadata --write-out '%{http_code}' --silent --output /dev/null --verbose --data "@${full_path}" -H "Content-Type: application/json" )

If I run the following:

#!/bin/bash

submit_request () {
  full_path=/home/mat/globalmetadata.json

  header_option=""
  header_options=""
  for header in "${@:1}"; do # looping over the  elements of the $@ array ($1, $2...)
    header_option=$(printf " -H %s" "$header")
    header_options=$(printf '%s%s' "$header_options" "$header_option")
  done

  echo Headers: $header_options

  executable=curl

  #response=$($executable -X POST localhost:9200/index-template/globalmetadata --write-out '%{http_code}' --silent --output /dev/null --verbose --data "@${full_path}" -H "Content-Type: application/json" )
  response=$($executable -X POST localhost:9200/index-template/globalmetadata --write-out '%{http_code}' --silent --output /dev/null --verbose --data "@${full_path}" $header_option )

  echo $response

}

submit_request "\"Content-Type: application/json\""

I get this output:

Headers: -H "Content-Type: application/json"
======= 3
*   Trying 127.0.0.1:9200...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9200 (#0)
> POST /index-template/globalmetadata HTTP/1.1
> Host: localhost:9200
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Length: 3232
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 100 Continue
} [3232 bytes data]
* We are completely uploaded and fine
* Mark bundle as not supporting multiuse
< HTTP/1.1 406 Not Acceptable
< X-elastic-product: Elasticsearch
< content-type: application/json; charset=UTF-8
< content-length: 97
< 
{ [97 bytes data]
* Connection #0 to host localhost left intact
* Could not resolve host: application
* Closing connection 1
406000

What I have noticed is that even though the headers are -H "Content-Type: application/json, curl says Could not resolve host: application. I suspect that it splits the arguments into two due to space between Content-Type: and application/json.

I tried to mix and match quotes and double quotes in all kinds of combination but nothing really worked.

CodePudding user response:

@GordonDavisson is right, you'll have to put your header_options in an array. Just be aware that using the array "${header_options[@]}" when it is empty will result in an empty argument in your curl command, but You can get rid of this problem by storing the whole command in an other array.

submit_request () {

    local -a header_options
    for arg; do header_options =(-H "$arg"); done

    local -a curl_command=( \
        curl \
        -X POST \
        localhost:9200/index-template/globalmetadata \
        --write-out '%{http_code}' \
        --silent \
        --output /dev/null \
        --verbose \
        --data '@/home/mat/globalmetadata.json' \
        "${header_options[@]}" \
    )

    local response=$( "${curl_command[@]}" )

    printf '%s\n' "$response"
}
  • Related