How to split the HTTP error code from the contents in cURL

bashcurl

Yes, this is related to Getting curl to output HTTP status code? but unfortunately not the same.

In a script I would like to run:

curl -qSfsw %{http_code} URL

where the -f option ensures that the exit code is non-zero to signal an error. On success I want to get the (textual) output from the fetched file, whereas otherwise I want to use the error code.

Problem:

  • Due to race conditions I must not use more than a single HTTP request
  • I cannot use a temporary file for storage of the content

How can I still split the HTTP return code from the actual output?


Pseudo code:

fetch URL
if http-error then
  print http-error-code
else
  print http-body # <- but without the HTTP status code
endif

Best Answer

There is no need to use a temporary file. The following bash script snippet send a single request and prints the exit code of curl and the HTTP status code, or the HTTP status code and response, as appropriate.

# get output, append HTTP status code in separate line, discard error message
OUT=$( curl -qSfsw '\n%{http_code}' http://superuser.com ) 2>/dev/null

# get exit code
RET=$?

if [[ $RET -ne 0 ]] ; then
    # if error exit code, print exit code
    echo "Error $RET"

    # print HTTP error
    echo "HTTP Error: $(echo "$OUT" | tail -n1 )"
else
    # otherwise print last line of output, i.e. HTTP status code
    echo "Success, HTTP status is:"
    echo "$OUT" | tail -n1

    # and print all but the last line, i.e. the regular response
    echo "Response is:"
    echo "$OUT" | head -n-1
fi

head -n-1 (print all but the last line) requires GNU, doesn't work on BSD/OS X.