15

I want a script to curl to a file and to put the status code into a variable (or, at least enable me to test the status code)

I can see I can do it in two calls with e.g.

url=https://www.gitignore.io/api/nonexistentlanguage
x=$(curl -sI $url | grep HTTP | grep -oe '\d\d\d')
if [[ $x != 200  ]] ; then
  echo "$url SAID $x" ; return
fi
curl $url # etc ...

but presumably there's a way to avoid the redundant extra call?

$? doesn't help: status code 404 still gets an return code of 0

5
  • 1
    curl -v will give you the header and body.
    – jesse_b
    Mar 11, 2020 at 22:39
  • 3
    Use --output to write the content to a (temporary) file, and --write-out to output things like HTTP status. man curl is your friend.
    – 9000
    Mar 11, 2020 at 23:09
  • Ah yes, using both --write-out and --output together gives me 2 separate outputs so something like x=$(curl -s https://www.gitignore.io/api/404 --write-out '%{http_code}' -o o.txt) would do it. Yes, thanks. Mar 11, 2020 at 23:59
  • curl -v would give me a load more stuff to process, like stripping out the tracing of the connection handshake etc? Mar 12, 2020 at 0:02
  • Crossdupes stackoverflow.com/questions/38906626/… and stackoverflow.com/questions/54038132/… (although probably now considered offtopic) and superuser.com/questions/272265/… Oct 13, 2023 at 2:45

3 Answers 3

29
#!/bin/bash

URL="https://www.gitignore.io/api/nonexistentlanguage"

response=$(curl -s -w "%{http_code}" $URL)

http_code=$(tail -n1 <<< "$response")  # get the last line
content=$(sed '$ d' <<< "$response")   # get all but the last line which contains the status code

echo "$http_code"
echo "$content"

(There are other ways like --write-out to a temporary file. But my example does not need to touch the disk to write any temporary file and remembering to delete it; everything is done in RAM)

4
  • thanks I hadn't noticed that using -w still emits the full response first then the -w parameter output Mar 13, 2020 at 14:28
  • 11
    Almost! on my system (OSX) i needed a newline before http_code "'\n%{http_code}'%{http_code}" Jun 5, 2020 at 19:19
  • 1
    The newline was missing for me too. But this worked: http_code=${response: -3} # get the last 3 digits and content=$(echo ${response} | head -c-4) # get all but the last 3 digits Jun 9, 2021 at 7:06
  • 1
    add -L option to curl due to gitignore.io redirection to toptal.com/developers/gitignore
    – froque
    Jul 23, 2021 at 10:19
2

Using --write-out and a temporary file got me to :

  url="https://www.gitignore.io/api/$1"
  tempfile=$(mktemp)

  code=$(curl -s $url --write-out '%{http_code}' -o $tempfile)

  if [[ $code != 200  ]] ; then
    echo "$url SAID $code"
    rm -f $tempfile
    return $code
  fi
  mv $tempfile $target
1
  • if curl failed, ur temporary file will be filled up a lot and can crash your site.
    – MaXi32
    Dec 12, 2022 at 16:55
1

Since curl 7.76.0 there is an option to do this without the extra call, --fall-with-body

curl -sI --fail-with-body $url

Curl will fail with code 22 if the request returns any HTTP status code above 400 but will return the body regardless the status code.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .