Consider, I have a shell script abc.sh
execute_curl() {
curl_command="curl"
for arg in "$@"; do
curl_command=$(printf "%s %s" "$curl_command" "$arg")
done
eval "$curl_command"
}
URL='https://some.github.com/api/v3/repos/gimlet-dev-repos/repository-name/contents/file.name?ref=branch-name’
execute_curl -s -H “Authorization: token ${TOKEN}” -H "Accept: application/vnd.github.v3+json" -L ”${URL}"
And test.bats for the same
@test "test-run-command perform" {
export PATH="${RESOURCES_DIR}/mocks/:${PATH}"
TEMP_DIR=$(mktemp -d)
debug "TEMP_DIR: ${TEMP_DIR}"
run abc -t TOKEN -d 'some.github.com' -o 'myorg' -r 'myrepo' -g "${RESOURCES_DIR}/mock-global" -b branch -a "${TEMP_DIR}"
assert_success
}
and in mocks directory, I have curl file to test the curl: for example:
#!/bin/sh
string_matches_glob() {
eval "
case \$1 in
$2) return 0 ;;
*) return 1 ;;
esac
"
}
while getopts "H:L:o:w:" OPT; do
case "${OPT}" in
o) OUTPUT_FILE="${OPTARG}" ;;
L) CURL_URL="${OPTARG}" ;;
?) ;;
esac
done
if string_matches_glob "${CURL_URL}" ‘*/contents/file.name*’; then
echo '
Content…
' >"${OUTPUT_FILE}"
printf '%s' '200'
else
exit 97
fi
Issue is if I don’t use execute_curl and use directly the curl command with argument, the tests pass but when I use execute_curl function test fails with 97.
more explanation of curl file above:
string_matches_glob evaluates whether the first argument matches the glob pattern specified in the second argument. The script then uses the getopts command to parse command-line options and arguments passed to the script.
There are three options that can be passed to the script:
-o: specifies the output file for the script to write to -L: specifies the URL to be passed to string_matches_glob
If the URL does not match any of the specified patterns, the script exits with an error code of 97.
My thinking is this line is not able to match the curl_url: if string_matches_glob "${CURL_URL}" ‘/contents/file.name’
Can you please help with changes in curl file so the test passes.
When I call
bash abc.sh, the call seems to work.However, when debugging (using
TOKEN=foo bash -x abc.sh) reveals that the command that is executed is:So one thing that immediately stands out is that the way the
curl_commandis built and executed does not properly handle whitespace.curlwill see-H Authorization:and-H Accept:but ignore the actual values of the provided headers.There is page on the awesome BashFAQ dedicated to the pitfalls of how to properly do this: http://mywiki.wooledge.org/BashFAQ/050
Using a proper solution also removes the need for
eval:This will create the expected
curlcommand, with proper whitespacing:Not sure if this will resolve your issue but at least the call to
curlwill be correct.What stands out next, is that the call in the test does not match a
curlcall.As in, this call:
would constitute this
curlcall:which I don't think is what you want.
This makes me think that there is more going on in the real code than what is represented in the more minimal example.
The most likely answer is that the
curl_commanduses the input to construct the correct URL (-d= 'domain',-o= 'org',-r='repo'?) but that is just a guess.Finally, let's address the
evalinstring_matches_glob. I assume this is to allow dynamically matching$1against$2. If that is the case, there are easier ways to do this, withoutevalor `case.For instance, using the
=~Regular Expression matching operator:or, if that is not available or desirable, using
grep:As both solutions are sufficiently small, they can be used inline, without the need for a separate function:
or:
You may be wondering "Why does this matter?" but the less magic you have in your code, the easier it is to debug.
All of these things make me think we don't have enough of the real code to properly debug the issue, although the most likely culprit is the
curl_commandconstruction.