Curl para retornar o código de status http junto com a resposta

110

Eu uso curl para obter cabeçalhos http para encontrar o código de status http e também retornar uma resposta. Recebo os cabeçalhos http com o comando

curl -I http://localhost

Para obter a resposta, uso o comando

curl http://localhost

Assim que uso o sinalizador -I, obtenho apenas os cabeçalhos e a resposta não está mais lá. Existe uma maneira de obter a resposta http e o código de status headers / http em um comando?

randominstanceOfLivingThing
fonte
1
Aqui está um snippet muito útil gist.github.com/maxcnunes/9f77afdc32df354883df
rocketspacer

Respostas:

111

Consegui obter uma solução olhando para o documento curl que especifica o uso -para a saída para obter a saída para stdout.

curl -o - http://localhost

Para obter a resposta apenas com o código de retorno http, eu poderia apenas fazer

curl -o /dev/null -s -w "%{http_code}\n" http://localhost
randominstanceOfLivingThing
fonte
12
ou você usaria -i. Ou talvez -vse você quiser alguma informação adicional também.
Daniel Stenberg
2
Obrigado @DanielStenberg. A resposta aceita não funcionou para mim, simplesmente usar -i funcionou.
Alejandro Cotilla
seu segundo comando está faltando -I @randominstanceOfLivingThing, a menos que seja intencionalmente uma opção em branco? Não funciona para mim sem ele
mdo123
2
-o -Iacaba criando um arquivo chamado literalmente ' -I' no CWD. Alguém mais vê isso? A solução para isso é-o/dev/null -I
JDS
Removido o -I. Eu percebi e corrigi agora. Você não precisa do -I.
randominstanceOfLivingThing
42

o modo verboso vai te dizer tudo

curl -v http://localhost
ScotchAndSoda
fonte
36

Eu uso este comando para imprimir o código de status sem qualquer outra saída. Além disso, ele executará apenas uma solicitação HEAD e seguirá o redirecionamento (respectivamente -Ie -L).

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

Isso torna muito fácil verificar o código de status em um script de integridade:

sh -c '[ $(curl -o -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]'
scriptracer
fonte
5
Isso já foi respondido há um ano. Que novo valor sua resposta traz? Escreva também alguma explicação para a sua resposta.
Maciej Jureczko 01 de
11
@MaciejJureczko - O valor é simples. Para fins de script, esta resposta é a melhor de todas as outras respostas, porque fornece um único código de status em vez de muitas linhas de lixo junto com o referido código de status.
aggregate1166877
2
Mas o OP afirma especificamente que eles querem tanto o código de status e o corpo da resposta. Eles sabem apenas como obter o código de resposta (declarado na pergunta)
wottle
2
Sempre que eu uso isso, curl -o -I -L -s -w "%{http_code}" http://localhostum arquivo é criado chamado -I, para contornar isso eu adicionei um local para a saída do arquivo implícito -oem ir, a saber /dev/null:curl -o /dev/null -I -L -s -w "%{http_code}" http://localhost
assunto
HEAD nem sempre resultará na mesma saída de um pedido, até o servidor como eles respondem. Portanto, esta não é realmente uma resposta.
Eddie
28

Eu encontrei esta pergunta porque eu queria AMBOS a resposta e o conteúdo, a fim de adicionar algum tratamento de erro para o usuário.

Você pode imprimir o código de status HTTP para saída padrão e gravar o conteúdo em outro arquivo.

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

Isso permite que você use a lógica para decidir se vale a pena processar a resposta.

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
fonte
o que é http_code? Eu não entendo isso, precisa de mais explicações, pls
Alexander Mills
esclarecido acima, refere-se ao código de status HTTP - developer.mozilla.org/en-US/docs/Web/HTTP/Status
Eddie
22

A -iopção é a que você deseja:

curl -i http://localhost

-i, --include Inclui cabeçalhos de protocolo na saída (H / F)

Como alternativa, você pode usar a opção detalhada:

curl -v http://localhost

-v, --verbose Torna a operação mais falante

Owen Pauling
fonte
16

Eu usei isto:

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

Para obter o status HTTP

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

Para obter o corpo de resposta, usei este

    output_response=$(echo "$request_cmd" | grep body)
    echo $output_response
user2720864
fonte
8

Este comando

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

obterá o corpo e o status separados por vírgulas; você pode dividi-los para tirá-los.

Você pode alterar o delimitador como desejar.

Viciado em tecnologia
fonte
2
boa dica! é possível adicionar código de status na frente da saída?
Psicozóico
6

Para uso programático, eu uso o seguinte:

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

Mostra a seguinte saída:

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

Esta é uma maneira de recuperar o corpo "E" o código de status e formatá-lo para um json adequado ou qualquer formato que funcione para você. Alguns podem argumentar que é o uso incorreto da opção de formato de gravação, mas isso funciona para mim quando preciso do corpo e do código de status em meus scripts para verificar o código de status e retransmitir as respostas do servidor.

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

execute o código acima e você deve obter um json neste formato:

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

com a opção de formato de gravação -w, uma vez que stderr é impresso primeiro, você pode formatar sua saída com var http_code e colocar o corpo da resposta em um valor (corpo) e seguir o fechamento usando var stdout. Em seguida, redirecione sua saída stderr para stdout e você será capaz de combinar http_code e corpo de resposta em uma saída elegante

Huy Tran
fonte
1
Tenho o seguinte erro - curl: unknown --write-out variable: 'stderr'ecurl: unknown --write-out variable: 'stdout'
ALex_hha
curl.haxx.se/docs/manpage.html página de manual mostra a variável disponível. não tenho certeza por que o stderr não é reconhecido pelo seu curl, o curl está em um macbook. A partir deste documento curl do Linux, computerhope.com/unix/curl.htm , também não vejo stderr como uma variável. Talvez esta seja uma variação do sistema operacional.
Huy Tran
O único problema que tenho com isso é se seu corpo tiver aspas, como se for json, o corpo fará a resposta json acima json inválida
theannouncer
justo @theannouncer, eu esperaria que o dev se ajustasse de acordo, pois nem todas as respostas serão json padrão. Houve alguns casos em que tive que ajustar devido à natureza da resposta.
Huy Tran
1

Minha maneira de conseguir isso :

Para obter ambos (cabeçalho e corpo), geralmente executo um curl -D- <url>como em:

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

Isso irá despejar headers ( -D) em stdout ( -) (Procure --dump-headerem man curl ).

IMHO também é muito útil neste contexto:

Costumo usar jq para obter os dados json (por exemplo, de algumas APIs restantes) formatados. Mas, como o jq não espera um cabeçalho HTTP, o truque é imprimir os cabeçalhos no stderr usando -D/dev/stderr. Observe que, desta vez, também usamos -sS(--silent, --show-errors) para suprimir o medidor de progresso (porque gravamos em um tubo).

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

Eu acho que isso também pode ser útil se você quiser imprimir cabeçalhos (para inspeção rápida) para o console, mas redirecionar o corpo para um arquivo (por exemplo, quando é algum tipo de binário para não bagunçar o seu 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

Esteja ciente: NÃO é o mesmo que curl -I <url>! As -Iexecutará uma HEADsolicitação e não uma GETsolicitação (Procure --headem man curl . Sim: para a maioria dos servidores HTTP, isso produzirá o mesmo resultado. Mas eu conheço muitos aplicativos de negócios que não implementam HEADsolicitação de forma alguma ;-P

hiddenAlpha
fonte
-2
while : ; do curl -sL -w "%{http_code} %{url_effective}\\n" http://host -o /dev/null; done
Peter
fonte
1
Por que você colocaria isso em um loop while? Por favor, expanda e explique sua resposta.
Uberhumus