0

I am providing a snippet of a bash script that's called at some regular interval. I cannot seem to get the JSON that must be submitted to be properly escaped (web server says required field is missing):

url="http://myurl"
json='{\"rollingRestartStrategy\":\"\"}'

request_cmd="$(curl -u ${CATTLE_ACCESS_KEY}:${CATTLE_SECRET_KEY} -X POST -H 'Accept: application/json' -d $json $url)"

output=$(echo "$request_cmd")

Error message:

{"id":"04723a42-c2b4-4181-839d-a8ca5180434b","type":"error","links":{},"actions":{},"status":422,"code":"MissingRequired","message":null,"detail":null,"fieldName":"rollingRestartStrategy","baseType":"error"}
4
  • Run echo "$json" and the problem is obvious. Commented Nov 29, 2017 at 17:21
  • ...well, one of the problems. Run your code through shellcheck.net for some of the others. Commented Nov 29, 2017 at 17:22
  • and output=$(echo "$request_cmd") does nothing useful whatsoever; you could just have called the variable output=$(curl ...) instead of assigning request_cmd in the first place. Commented Nov 29, 2017 at 17:25
  • (...and beyond that, var2=$(echo "$var1") introduces bugs that just var2=$var1 wouldn't have; if var1='-n' or contains literal backslashes, output from echo is undefined by the POSIX standard, and varies between implementations). Commented Nov 29, 2017 at 17:32

1 Answer 1

2

Fixing The Assignment (As Literal Data)

Double quotes are already literal inside single quotes. You don't need to escape them further with backslashes (and can't, because when inside single quotes those backslashes are also literal -- which is to say, parsed as data rather than as syntax).

# THIS IS BAD; the value assigned is: {\"rollingRestartStrategy\":\"\"} -- not valid JSON
json='{\"rollingRestartStrategy\":\"\"}'

# THIS IS GOOD: the value assigned is: {"rollingRestartStrategy":""}
json='{"rollingRestartStrategy":""}'

Fixing The Assignment (If Passing Shell Variables)

Let's say that instead of being a literal value, you actually want to use a shell variable to set the strategy. In that case, the best practice is to use jq:

strategy="whatever"
json=$(jq -cn --arg strategy "$strategy" '{ "rollingRestartStrategy": $strategy }')

This will generate well-formed JSON for every possible strategy -- even values that contain literal quotes, literal newlines, or other surprising weirdness.

Fixing The Usage

Always, always quote expansions (except in a scenario that specifically doesn't require it -- such as assignments, which are immune from expansion-time string-splitting and glob expansion even when unquoted). And note that command substitution with $() creates a new quoting context, so quotes used inside a command substitution won't interact with quotes used outside it.

output=$(curl -u "${CATTLE_ACCESS_KEY}:${CATTLE_SECRET_KEY}" \
              -X POST \
              -H 'Accept: application/json' \
              -d "$json" \
              "$url")
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.