This is a painful curl --fail
limitation. From man curl
:
-f, --fail (HTTP) Fail silently (no output at all) on server errors
But there is no way to get both the non-zero return code AND the response body in stdout.
Based on pvandenberk's answer and this other very useful trick learned on SOthis other very useful trick learned on SO, here is a workaround :
curl_with_error_code () {
_curl_with_error_code "$@" | sed '$d'
}
_curl_with_error_code () {
local curl_error_code http_code
exec 17>&1
http_code=$(curl --write-out '\n%{http_code}\n' "$@" | tee /dev/fd/17 | tail -n 1)
curl_error_code=$?
exec 17>&-
if [ $curl_error_code -ne 0 ]; then
return $curl_error_code
fi
if [ $http_code -ge 400 ] && [ $http_code -lt 600 ]; then
echo "HTTP $http_code" >&2
return 127
fi
}
This function behaves exactly as curl
, but will return 127 (a return code non-used by curl
) in case of a HTTP code in the range [400, 600[.