Curl para devolver el código de estado http junto con la respuesta

111

Utilizo curl para obtener encabezados http para encontrar el código de estado http y también devolver la respuesta. Obtengo los encabezados http con el comando

curl -I http://localhost

Para obtener la respuesta, uso el comando

curl http://localhost

Tan pronto como uso la bandera -I, obtengo solo los encabezados y la respuesta ya no está allí. ¿Hay alguna manera de obtener tanto la respuesta http como los encabezados / código de estado http en un solo comando?

randominstanceOfLivingThing
fuente
1
Aquí hay un fragmento muy útil gist.github.com/maxcnunes/9f77afdc32df354883df
rocketspacer

Respuestas:

112

Pude obtener una solución mirando el doc curl que especifica usar -para que la salida obtenga la salida a la salida estándar.

curl -o - http://localhost

Para obtener la respuesta con solo el código de retorno http, podría hacer

curl -o /dev/null -s -w "%{http_code}\n" http://localhost
randominstanceOfLivingThing
fuente
12
o usarías -i. O tal vez -vsi también desea información adicional.
Daniel Stenberg
2
Gracias @DanielStenberg. La respuesta aceptada no funcionó para mí, simplemente usar -i funcionó.
Alejandro Cotilla
falta su segundo comando -I @randominstanceOfLivingThing, a menos que sea intencionalmente una opción en blanco? Sin embargo
mdo123
2
-o -Itermina creando un archivo llamado literalmente ' -I' en el CWD. ¿Alguien más puede ver esto? La solución para eso es-o/dev/null -I
JDS
Se eliminó el -I. Lo noté y lo corrigí ahora. No necesitas el -I.
randominstanceOfLivingThing
42

el modo detallado te dirá todo

curl -v http://localhost
ScotchAndSoda
fuente
36

Utilizo este comando para imprimir el código de estado sin ningún otro resultado. Además, solo realizará una solicitud HEAD y seguirá la redirección (respectivamente -Iy -L).

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

Esto hace que sea muy fácil verificar el código de estado en un script de salud:

sh -c '[ $(curl -o -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]'
scriptracer
fuente
5
Esto ya fue respondido hace un año. ¿Qué nuevo valor aporta tu respuesta? También escriba una explicación a su respuesta.
Maciej Jureczko
11
@MaciejJureczko - El valor es simple. Para fines de scripting, esta respuesta es la mejor de todas las demás respuestas, porque proporciona un código de estado único en lugar de muchas líneas de basura junto con dicho código de estado.
aggregate1166877
2
Pero el OP establece específicamente que quieren tanto el código de estado como el cuerpo de respuesta. Saben cómo obtener el código de respuesta (indicado en la pregunta)
wottle
2
Cada vez que uso esto curl -o -I -L -s -w "%{http_code}" http://localhost, se crea un archivo llamado -I, para evitar esto, agregué un lugar para la salida del archivo implícita -o, a saber /dev/null:curl -o /dev/null -I -L -s -w "%{http_code}" http://localhost
Thismatters
HEAD no siempre dará como resultado la misma salida que una solicitud, sin embargo, depende del servidor cómo responda. Entonces esta no es realmente una respuesta.
Eddie
28

Encontré esta pregunta porque quería TANTO la respuesta como el contenido para agregar un manejo de errores para el usuario.

Puede imprimir el código de estado HTTP en std y escribir el contenido en otro archivo.

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

Esto le permite usar la lógica para decidir si vale la pena procesar la respuesta.

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
fuente
¿Qué es http_code? No entiendo esto, necesita más explicación por favor
Alexander Mills
aclarado anteriormente, se refiere al código de estado HTTP - developer.mozilla.org/en-US/docs/Web/HTTP/Status
Eddie
22

La -iopción es la que tú quieras:

curl -i http://localhost

-i, --include Incluir encabezados de protocolo en la salida (H / F)

Alternativamente, puede utilizar la opción detallada:

curl -v http://localhost

-v, --verbose Hace que la operación sea más comunicativa

Owen Pauling
fuente
16

He usado esto:

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

Para obtener el estado HTTP

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

Para obtener el cuerpo de respuesta he usado esto

    output_response=$(echo "$request_cmd" | grep body)
    echo $output_response
usuario2720864
fuente
8

Este comando

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

obtendrá el cuerpo y el estado separados por comas; puedes dividirlos para sacarlos.

Puede cambiar el delimitador como desee.

Adicto a la tecnología
fuente
2
buena pista! ¿Es posible agregar un código de estado delante de la salida?
Psychozoic
6

Para uso programático, uso lo siguiente:

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

Muestra la siguiente salida:

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

Esta es una forma de recuperar el cuerpo "Y" el código de estado y formatearlo a un json adecuado o al formato que funcione para usted. Algunos pueden argumentar que es el uso incorrecto de la opción de formato de escritura, pero esto me funciona cuando necesito tanto el código de estado como el de cuerpo en mis scripts para verificar el código de estado y retransmitir las respuestas del servidor.

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

ejecute el código anterior y debería obtener un json en este formato:

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

con la opción -w write format, dado que stderr se imprime primero, puede formatear su salida con var http_code y colocar el cuerpo de la respuesta en un valor (body) y hacer un seguimiento del adjunto usando var stdout. Luego, redirija su salida stderr a stdout y podrá combinar tanto http_code como el cuerpo de respuesta en una salida ordenada

Huy Tran
fuente
1
Consiguió el siguiente error - curl: unknown --write-out variable: 'stderr'ycurl: unknown --write-out variable: 'stdout'
ALex_hha
La página de manual curl.haxx.se/docs/manpage.html muestra la variable disponible. No estoy seguro de por qué stderr no es reconocido por su curl, el curl está en un macbook. De este documento curl de Linux, computerhope.com/unix/curl.htm , tampoco veo stderr como una variable. Quizás esta sea una variación del sistema operativo.
Huy Tran
El único problema que tengo con esto es que si su cuerpo tiene comillas, como si es json, el cuerpo hará que la respuesta json sobre json no sea válida
theannouncer
bastante justo @theannouncer, esperaría que el desarrollador se ajustara en consecuencia, ya que no todas las respuestas serán json estándar. Hubo algunos casos en los que tuve que adaptarme debido a la naturaleza de la respuesta.
Huy Tran,
2

Mi forma de lograr esto :

Para obtener ambos (encabezado y cuerpo), generalmente realizo un curl -D- <url>como en:

$ 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"]}

Esto volcará los encabezados ( -D) a stdout ( -) (busque --dump-headeren man curl ).

En mi humilde opinión también es muy útil en este contexto:

A menudo uso jq para formatear esos datos json (por ejemplo, de algunas API de descanso). Pero como jq no espera un encabezado HTTP, el truco consiste en imprimir encabezados en stderr usando -D/dev/stderr. Tenga en cuenta que esta vez también usamos -sS(--silent, --show-errors) para suprimir el medidor de progreso (porque escribimos en una tubería).

$ 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"
  ]
}

Supongo que esto también puede ser útil si desea imprimir encabezados (para una inspección rápida) en la consola pero redirigir el cuerpo a un archivo (por ejemplo, cuando es algún tipo de binario para no estropear su 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

Tenga en cuenta: ¡Esto NO es lo mismo que curl -I <url>! Como -Irealizará una HEADsolicitud y no una GETsolicitud (busque --headen man curl . Sí: para la mayoría de los servidores HTTP, esto producirá el mismo resultado. Pero conozco muchas aplicaciones comerciales que no implementan la HEADsolicitud en absoluto ;-P

hiddenAlpha
fuente
-2
while : ; do curl -sL -w "%{http_code} %{url_effective}\\n" http://host -o /dev/null; done
Pedro
fuente
1
¿Por qué pondrías esto en un bucle while? Amplíe y explique su respuesta.
Uberhumus