492 votes

Puis-je faire en sorte que cURL échoue avec un exitCode différent de 0 si le code d'état HTTP n'est pas 200 ?

J'ai toujours supposé que lorsque curl obtenait une réponse HTTP 500, il retournait un code de sortie signifiant l'échec (!= 0), mais il semble que ce soit le cas. no l'affaire.

Existe-t-il un moyen de faire échouer cURL avec un exitCode différent de 0 si le code d'état HTTP n'est pas 200 ? Je sais que je peux utiliser -w "%{http_code}" mais cela le place dans STDOUT, pas comme code de sortie (de plus, je suis également intéressé par la capture de la sortie, que je ne veux pas rediriger vers un fichier, mais vers l'écran).

0 votes

Si vous arrivez ici bien après le 2021/02/15, veuillez noter qu'un drapeau a été ajouté à curl qui fait exactement que - voir superuser.com/a/1626376/25173 en dessous. Bien sûr, assurez-vous que votre version de curl est >= 7.76.0.

0 votes

C'est 2022 maintenant, et (selon mon exemple) le dernier docker LTS de Jenkins inclut ceci.

0 votes

Quel est le rapport entre Jenkins et ma question ?

9voto

shesek Points 171

Je suis arrivé à ce résultat en me basant sur Réponse de Dennis une ligne unique rapide qui échoue pour les codes d'état non-200 tout en conservant la sortie (vers stderr ):

[ $(curl ... -o /dev/stderr -w "%{http_code}") -eq 200 ]

0 votes

Parfois, la meilleure réponse n'est pas celle qui est acceptée ou celle qui recueille le plus de votes. Celle-ci fonctionne sur plusieurs plates-formes, car sur macos, vous n'avez pas la dernière version de curl qui a l'avantage d'être plus rapide. --fail-with-body ... même chose pour beaucoup d'autres plateformes. Moche, mais ça marche.

3voto

skipy Points 131

J'ai récemment eu besoin de quelque chose comme ça, mais je voulais aussi imprimer la sortie à tout moment. J'ai utilisé l'extraction http_code et grep pour y parvenir.

out=$(curl -H"Content-Type: application/json"  -w '\nstatus_code=%{http_code}\n' -s http://localhost:4040${uri} -d "${body}")
code=$(echo ${out}|grep status_code|awk -F"=" '{print $2}')
echo ${out}
if [[ ${code} -ge 400 ]];
then
    exit 2;
fi;

3voto

RJones Points 21

Cette solution est basée sur celle de @Dennis, mais ne montre la sortie qu'en cas d'erreur (le code de retour n'est pas le même). 200 ):

#!/bin/bash

# Create temp file, readable and writable only by current user and root
SCRATCH=$( umask 0077; mktemp -t tmp.XXXXXXXXXX )

# Cleanup temp file on script exit
function cleanup_on_exit {
    rm -f "$SCRATCH"
}
trap cleanup_on_exit EXIT

# Perform curl call
HTTP_CODE=$( curl -s -o "$SCRATCH" -w '%{http_code}' your..stuff..here )

# Analyze HTTP return code
if [ ${HTTP_CODE} -ne 200 ] ; then
    cat "${SCRATCH}"
    exit 1
fi

Traitement alternatif des codes de retour HTTP, où 2XX est OK :

# Analyze HTTP return code
if [ ${HTTP_CODE} -lt 200 ] || [ ${HTTP_CODE} -gt 299 ] ; then
    cat "${SCRATCH}"
    exit 1
fi

1 votes

Pourquoi ne pas utiliser un descripteur de fichier ou un fifo au lieu d'un fichier temporaire ? Cela semble un peu plus... unix-y.

1 votes

Excellente suggestion, @ErikE. Pourquoi n'écrirais-tu pas une réponse qui nous montre comment faire ? :)

1 votes

Jake, j'aimerais avoir le temps pour ça !

2voto

Voici ma solution - elle utilise jq et suppose que le corps est json

#  this code adds a statusCode field to the json it receives and then jq squeezes them together
# curl 7.76.0 will have curl --fail-with-body and thus eliminate all this
  local result
  result=$(
    curl -sL -w ' { "statusCode": %{http_code}} ' -X POST "${headers[@]}" "${endpoint}" \
      -d "${body}"  "$curl_opts" | jq -ren '[inputs] | add'
  )
#   always output the result
  echo "${result}"
#  jq -e will produce an error code if the expression result is false or null - thus resulting in a
# error return code from this function naturally. This is much preferred rather than assume/hardcode
# the existence of a error object in the body payload
  echo "${result}" | jq -re '.statusCode >= 200 and .statusCode < 300' > /dev/null

1voto

Gabriel Points 11

J'ai récemment essayé d'utiliser les approches présentées ici, mais j'avais toujours une erreur parce que curl fournissait le response_code sous la forme suivante 000401 alors qu'il devrait être 401 (curl 7.64.1 (x86_64-apple-darwin19.0). Bash convertit 000401 a 257 donc essayer de tester pour >=200 y <=299 n'était pas fiable.

Je me retrouve avec cette fonction :

function curl_custom() {
    local RESPONSE_CODE
    RESPONSE_CODE=$(curl -v --silent --output /dev/stderr --write-out "%{response_code}" "$@")

    # Remove leading zeros (if any) to prevent bash interpreting result as octal
    RESPONSE_CODE=${RESPONSE_CODE##+(0)}

    if (( RESPONSE_CODE >= 200 )) && (( RESPONSE_CODE <= 299 )) ; then
        echo "INFO - Got response ${RESPONSE_CODE}"
    else
        echo "ERROR - Request failed with ${RESPONSE_CODE}"
        return 127
    fi
}

Exemples d'utilisation :

curl_custom example.com example.com
curl_custom -X PUT -U user:pass file.json example.com/api

J'espère que cela vous aidera.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X