Curl pour renvoyer le code d'état http avec la réponse

114

J'utilise curl pour obtenir les en-têtes http pour trouver le code d'état http et aussi pour renvoyer la réponse. J'obtiens les en-têtes http avec la commande

curl -I http://localhost

Pour obtenir la réponse, j'utilise la commande

curl http://localhost

Dès que j'utilise le drapeau -I, je n'obtiens que les en-têtes et la réponse n'est plus là. Existe-t-il un moyen d'obtenir la réponse http et le code d'état des en-têtes / http en une seule commande?

randominstanceOfLivingThing
la source
1
Voici un extrait très utile gist.github.com/maxcnunes/9f77afdc32df354883df
rocketspacer

Réponses:

114

J'ai pu obtenir une solution en regardant la doc curl qui spécifie à utiliser -pour la sortie pour obtenir la sortie vers stdout.

curl -o - http://localhost

Pour obtenir la réponse avec juste le code de retour http, je pourrais simplement faire

curl -o /dev/null -s -w "%{http_code}\n" http://localhost
randominstanceOfLivingThing
la source
14
ou vous utiliseriez -i. Ou peut -v- être si vous aimez aussi des informations supplémentaires.
Daniel Stenberg
2
Merci @DanielStenberg. La réponse acceptée n'a pas fonctionné pour moi, le simple fait d'utiliser -i a fonctionné.
Alejandro Cotilla
votre deuxième commande est manquante -I @randominstanceOfLivingThing, à moins que ce ne soit intentionnellement une option vide? Cela ne fonctionne pas pour moi sans cela
mdo123
2
-o -Ifinit par créer un fichier nommé littéralement « -I» dans le CWD. Quelqu'un d'autre voit-il cela? La solution pour cela est-o/dev/null -I
JDS
Suppression du -I. J'ai remarqué et corrigé maintenant. Vous n'avez pas besoin du -I.
randominstanceOfLivingThing
42

le mode verbeux vous dira tout

curl -v http://localhost
ScotchAndSoda
la source
36

J'utilise cette commande pour imprimer le code d'état sans aucune autre sortie. De plus, il n'effectuera qu'une requête HEAD et suivra la redirection (respectivement -Iet -L).

curl -o -I -L -s -w "%{http_code}" http://localhost

Cela facilite la vérification du code d'état dans un script de santé:

sh -c '[ $(curl -o -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]'
scripttracer
la source
5
Cela a déjà été répondu il y a un an. Quelle nouvelle valeur apporte votre réponse? Veuillez également expliquer votre réponse.
Maciej Jureczko
11
@MaciejJureczko - La valeur est simple. À des fins de script, cette réponse est la meilleure de toutes les autres réponses, car elle donne un code d'état unique au lieu de plusieurs lignes de déchets avec ledit code d'état.
aggregate1166877
2
Mais l'OP déclare spécifiquement qu'ils veulent à la fois le code d'état et le corps de la réponse. Ils savent comment obtenir simplement le code de réponse (indiqué dans la question)
wottle
2
Chaque fois que j'utilise cela, curl -o -I -L -s -w "%{http_code}" http://localhostun fichier est créé appelé -I, pour contourner ce -o/dev/nullcurl -o /dev/null -I -L -s -w "%{http_code}" http://localhost
problème,
HEAD n'entraînera pas toujours le même résultat qu'une requête, selon le serveur comment il répond. Ce n'est donc pas vraiment une réponse.
Eddie le
28

J'ai trouvé cette question parce que je voulais à la fois la réponse et le contenu afin d'ajouter une gestion des erreurs pour l'utilisateur.

Vous pouvez imprimer le code d'état HTTP sur std out et écrire le contenu dans un autre fichier.

curl -s -o response.txt -w "%{http_code}" http://example.com

Cela vous permet d'utiliser la logique pour décider si la réponse mérite d'être traitée.

http_response=$(curl -s -o response.txt -w "%{http_code}" http://example.com)
if [ $http_response != "200" ]; then
    # handle error
else
    echo "Server returned:"
    cat response.txt    
fi
Eddie
la source
qu'est-ce que http_code? Je ne comprends pas cela, a besoin de plus d'explications pls
Alexander Mills
clarifié ci-dessus, il fait référence au code d'état HTTP - developer.mozilla.org/en-US/docs/Web/HTTP/Status
Eddie
22

L' -ioption est celle que vous souhaitez:

curl -i http://localhost

-i, --include Inclure les en-têtes de protocole dans la sortie (H / F)

Vous pouvez également utiliser l'option verbose:

curl -v http://localhost

-v, --verbose Rendre l'opération plus bavarde

Owen Pauling
la source
16

J'ai utilisé ceci:

    request_cmd="$(curl -i -o - --silent -X GET --header 'Accept: application/json' --header 'Authorization: _your_auth_code==' 'https://example.com')"

Pour obtenir l'état HTTP

    http_status=$(echo "$request_cmd" | grep HTTP |  awk '{print $2}')
    echo $http_status

Pour obtenir le corps de réponse, j'ai utilisé ceci

    output_response=$(echo "$request_cmd" | grep body)
    echo $output_response
utilisateur2720864
la source
8

Cette commande

 curl http://localhost -w ", %{http_code}"

obtiendra le corps et le statut séparés par des virgules; vous pouvez les séparer pour les sortir.

Vous pouvez modifier le délimiteur à votre guise.

Accro à la technologie
la source
2
bon indice! est-il possible d'ajouter un code d'état devant la sortie?
Psychozoic
6

Pour une utilisation programmatique, j'utilise ce qui suit:

curlwithcode() {
    code=0
    # Run curl in a separate command, capturing output of -w "%{http_code}" into statuscode
    # and sending the content to a file with -o >(cat >/tmp/curl_body)
    statuscode=$(curl -w "%{http_code}" \
        -o >(cat >/tmp/curl_body) \
        "$@"
    ) || code="$?"

    body="$(cat /tmp/curl_body)"
    echo "statuscode : $statuscode"
    echo "exitcode : $code"
    echo "body : $body"
}

curlwithcode https://api.github.com/users/tj

Il montre la sortie suivante:

statuscode : 200
exitcode : 0
body : {
  "login": "tj",
  "id": 25254,
  ...
}
edi9999
la source
5

C'est une façon de récupérer le corps "ET" le code d'état et de le formater dans un json approprié ou tout autre format qui fonctionne pour vous. Certains peuvent argumenter que c'est l'utilisation incorrecte de l'option de format d'écriture, mais cela fonctionne pour moi lorsque j'ai besoin à la fois du corps et du code d'état dans mes scripts pour vérifier le code d'état et relayer les réponses du serveur.

curl -X GET -w "%{stderr}{\"status\": \"%{http_code}\", \"body\":\"%{stdout}\"}"  -s -o - https://github.com 2>&1

exécutez le code ci-dessus et vous devriez récupérer un json dans ce format:

{
"status" : <status code>,
"body" : <body of response>
}

avec l'option -w write format, puisque stderr est imprimé en premier, vous pouvez formater votre sortie avec le var http_code et placer le corps de la réponse dans une valeur (corps) et suivre la clôture en utilisant var stdout. Ensuite, redirigez votre sortie stderr vers stdout et vous pourrez combiner à la fois http_code et le corps de la réponse en une sortie soignée

Huy Tran
la source
1
Vous avez l'erreur suivante - curl: unknown --write-out variable: 'stderr'etcurl: unknown --write-out variable: 'stdout'
ALex_hha le
La page de manuel curl.haxx.se/docs/manpage.html montre la variable disponible. Je ne sais pas pourquoi stderr n'est pas reconnu par votre curl, le curl im sur un macbook. D'après ce document curl Linux, computerhope.com/unix/curl.htm , je ne vois pas non plus stderr comme une variable. C'est peut-être une variante du système d'exploitation.
Huy Tran
le seul problème que j'ai avec ceci est si votre corps a des guillemets, comme si son json, le corps rendra la réponse json au-dessus de json invalide
theannouncer
assez juste @theannouncer, je m'attendrais à ce que le développeur s'ajuste en conséquence, car toutes les réponses ne seront pas du json standard. Il y a eu certains cas que j'ai dû ajuster en raison de la nature de la réponse.
Huy Tran le
2

Ma façon d'y parvenir :

Pour obtenir les deux (en-tête et corps), j'effectue généralement un curl -D- <url>comme dans:

$ curl -D- http://localhost:1234/foo
HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
Date: Wed, 29 Jul 2020 20:59:21 GMT

{"data":["out.csv"]}

Cela videra les en-têtes ( -D) dans stdout ( -) (Cherchez --dump-headerdans man curl ).

IMHO également très pratique dans ce contexte:

J'utilise souvent jq pour mettre en forme ces données json (par exemple à partir de certaines API restantes). Mais comme jq ne s'attend pas à un en-tête HTTP, l'astuce consiste à imprimer les en-têtes vers stderr en utilisant -D/dev/stderr. Notez que cette fois, nous utilisons également -sS(--silent, --show-errors) pour supprimer la barre de progression (car nous écrivons dans un tube).

$ curl -sSD/dev/stderr http://localhost:1231/foo | jq .
HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
Date: Wed, 29 Jul 2020 21:08:22 GMT

{
  "data": [
    "out.csv"
  ]
}

Je suppose que cela peut également être pratique si vous souhaitez imprimer des en-têtes (pour une inspection rapide) sur la console mais rediriger le corps vers un fichier (par exemple, lorsque c'est une sorte de binaire pour ne pas gâcher votre terminal):

$ curl -sSD/dev/stderr http://localhost:1231 > /dev/null
HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
Date: Wed, 29 Jul 2020 21:20:02 GMT

Attention: ce n'est PAS la même chose que curl -I <url>! Comme -Ieffectuera une HEADrequête et non une GETrequête (Cherchez --headdans man curl . Oui: Pour la plupart des serveurs HTTP, cela donnera le même résultat. Mais je connais beaucoup d'applications métier qui n'implémentent pas du tout la HEADrequête ;-P

hiddenAlpha
la source
-2
while : ; do curl -sL -w "%{http_code} %{url_effective}\\n" http://host -o /dev/null; done
Peter
la source
1
Pourquoi mettriez-vous cela dans une boucle while? Veuillez développer et expliquer votre réponse.
Uberhumus