Curl, aby wraz z odpowiedzią zwrócić kod stanu http

114

Używam curl, aby uzyskać nagłówki http, aby znaleźć kod statusu http, a także zwrócić odpowiedź. Otrzymuję nagłówki http z poleceniem

curl -I http://localhost

Aby uzyskać odpowiedź, używam polecenia

curl http://localhost

Gdy tylko użyję flagi -I, otrzymuję tylko nagłówki i nie ma już odpowiedzi. Czy istnieje sposób, aby w jednym poleceniu uzyskać zarówno odpowiedź http, jak i nagłówki / kod stanu http?

randominstanceOfLivingThing
źródło
1
Oto bardzo przydatny fragment gist.github.com/maxcnunes/9f77afdc32df354883df
rocketspacer,

Odpowiedzi:

114

Udało mi się uzyskać rozwiązanie, patrząc na dokument curl, który określa, że ​​należy użyć -wyjścia, aby uzyskać dane wyjściowe na stdout.

curl -o - http://localhost

Aby uzyskać odpowiedź tylko z kodem powrotu http, mogłem po prostu zrobić

curl -o /dev/null -s -w "%{http_code}\n" http://localhost
randominstanceOfLivingThing
źródło
14
lub użyjesz -i. A może -vchcesz też uzyskać dodatkowe informacje.
Daniel Stenberg,
2
Dzięki @DanielStenberg. Zaakceptowana odpowiedź nie zadziałała dla mnie, po prostu użycie -i działało.
Alejandro Cotilla
w drugim poleceniu brakuje -I @randominstanceOfLivingThing, chyba że jest to celowo pusta opcja? Jednak bez niego nie działa
mdo123
2
-o -Ikończy się utworzeniem pliku o nazwie dosłownie „ -I” w CWD. Czy ktoś jeszcze to widzi? Rozwiązaniem jest-o/dev/null -I
JDS
Usunięto -I. Zauważyłem i poprawiłem teraz. Nie potrzebujesz -I.
randominstanceOfLivingThing
42

tryb gadatliwy powie ci wszystko

curl -v http://localhost
ScotchAndSoda
źródło
36

Używam tego polecenia, aby wydrukować kod stanu bez żadnego innego wyjścia. Ponadto wykona tylko żądanie HEAD i podąży za przekierowaniem (odpowiednio -Ii -L).

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

To bardzo ułatwia sprawdzenie kodu stanu w skrypcie kondycji:

sh -c '[ $(curl -o -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]'
scriptracer
źródło
5
Na to odpowiedziano już rok temu. Jaką nową wartość wnosi twoja odpowiedź? Prosimy również o wyjaśnienie swojej odpowiedzi.
Maciej Jureczko
11
@MaciejJureczko - Wartość jest prosta. Dla celów tworzenia skryptów ta odpowiedź jest najlepsza ze wszystkich innych odpowiedzi, ponieważ daje pojedynczy kod statusu zamiast wielu wierszy śmieci wraz ze wspomnianym kodem stanu.
agregat1166877
2
Ale OP wyraźnie stwierdza, że ​​chcą zarówno kod stanu, jak i treść odpowiedzi. Wiedzą, jak uzyskać kod odpowiedzi (podany w pytaniu)
wottle
2
Za każdym razem, gdy tego używam, curl -o -I -L -s -w "%{http_code}" http://localhosttworzony jest plik o nazwie -I, aby obejść ten problem, dodałem miejsce na plik wyjściowy sugerowany przez -o, a mianowicie /dev/null:curl -o /dev/null -I -L -s -w "%{http_code}" http://localhost
Thismatters
Jednak HEAD nie zawsze daje takie same dane wyjściowe jak żądanie, zależnie od sposobu odpowiedzi serwera. Więc to nie jest tak naprawdę odpowiedź.
Eddie
28

Znalazłem to pytanie, ponieważ chciałem ZARÓWNO odpowiedzi, jak i treści, aby dodać obsługę błędów dla użytkownika.

Możesz wydrukować kod stanu HTTP na standardowe wyjście i zapisać zawartość w innym pliku.

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

Dzięki temu możesz użyć logiki, aby zdecydować, czy odpowiedź jest warta przetworzenia.

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
źródło
co to jest kod_http? Nie rozumiem tego, potrzebuje więcej wyjaśnień
Alexander Mills
wyjaśnione powyżej, odnosi się do kodu statusu HTTP - developer.mozilla.org/en-US/docs/Web/HTTP/Status
Eddie
22

Ta -iopcja jest taka, którą chcesz:

curl -i http://localhost

-i, --include Dołącz nagłówki protokołu do danych wyjściowych (H / F)

Alternatywnie możesz użyć opcji pełnej informacji:

curl -v http://localhost

-v, --verbose Spraw, aby operacja była bardziej rozmowna

Owen Pauling
źródło
16

Użyłem tego:

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

Aby uzyskać stan HTTP

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

Aby uzyskać treść odpowiedzi, użyłem tego

    output_response=$(echo "$request_cmd" | grep body)
    echo $output_response
user2720864
źródło
8

To polecenie

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

otrzyma treść i status oddzielone przecinkami; możesz je rozdzielić, aby je usunąć.

Możesz zmienić separator, jak chcesz.

Tech Junkie
źródło
2
dobra wskazówka! czy można dodać kod statusu przed wyjściem?
Psychozoic
6

Do zastosowań programistycznych używam:

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

Pokazuje następujące dane wyjściowe:

statuscode : 200
exitcode : 0
body : {
  "login": "tj",
  "id": 25254,
  ...
}
edi9999
źródło
5

Jest to sposób na pobranie treści „AND” z kodem stanu i sformatowanie go do odpowiedniego pliku json lub innego odpowiedniego formatu. Niektórzy mogą twierdzić, że jest to nieprawidłowe użycie opcji formatu zapisu, ale działa to w przypadku mnie, gdy potrzebuję zarówno treści, jak i kodu stanu w moich skryptach, aby sprawdzić kod stanu i przekazać odpowiedzi z serwera.

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

uruchom powyższy kod i powinieneś odzyskać json w tym formacie:

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

z opcją -w write format, ponieważ stderr jest wypisywane jako pierwsze, możesz sformatować swoje dane wyjściowe za pomocą var http_code i umieścić treść odpowiedzi w wartości (body), a następnie wykonać zamknięcie za pomocą var stdout. Następnie przekieruj wyjście stderr na stdout, a będziesz mógł połączyć zarówno kod http, jak i treść odpowiedzi w zgrabne wyjście

Huy Tran
źródło
1
curl: unknown --write-out variable: 'stderr'curl: unknown --write-out variable: 'stdout'
Pojawił się
Strona podręcznika curl.haxx.se/docs/manpage.html zawiera dostępne zmienne. Nie jestem pewien, dlaczego stderr nie jest rozpoznawany przez twoje curl, curl im na Macbooku. W tym dokumencie Linux curl, computerhope.com/unix/curl.htm , również nie widzę stderr jako zmiennej. Być może jest to odmiana systemu operacyjnego.
Huy Tran
Jedyny problem, który mam z tym, to to, że jeśli twoje ciało ma cudzysłowy, na przykład jeśli jest json, ciało spowoduje odpowiedź json powyżej nieprawidłowego json
theannouncer
dość uczciwy @theannouncer, spodziewałbym się, że programista odpowiednio się dostosuje, ponieważ nie wszystkie odpowiedzi będą standardowymi plikami json. Było kilka przypadków, do których musiałem się dostosować ze względu na naturę odpowiedzi.
Huy Tran
2

Mój sposób na osiągnięcie tego :

Aby uzyskać oba (nagłówek i treść), zwykle wykonuję curl -D- <url>jak w:

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

Spowoduje to zrzucenie nagłówków ( -D) do stdout ( -) (szukaj --dump-headerw man curl ).

IMHO również bardzo przydatne w tym kontekście:

Często używam jq, aby sformatować dane json (np. Z niektórych pozostałych API). Ale ponieważ jq nie oczekuje nagłówka HTTP, sztuczka polega na wydrukowaniu nagłówków na stderr za pomocą -D/dev/stderr. Zauważ, że tym razem używamy również -sS(--silent, --show-errors) do pomijania wskaźnika postępu (ponieważ piszemy do potoku).

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

Myślę, że może to być również przydatne, jeśli chcesz wydrukować nagłówki (w celu szybkiej kontroli) na konsoli, ale przekierować treść do pliku (np. Gdy jest to jakiś plik binarny, aby nie zepsuć terminalu):

$ 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

Uwaga: to NIE to samo, co curl -I <url>! Jak -Iwykona HEADżądanie, a nie GETżądanie (szukaj --headw man curl . Tak: dla większości serwerów HTTP da to ten sam wynik. Ale znam wiele aplikacji biznesowych, które w ogóle nie implementują HEADżądania ;-P

hiddenAlpha
źródło
-2
while : ; do curl -sL -w "%{http_code} %{url_effective}\\n" http://host -o /dev/null; done
Piotr
źródło
1
Dlaczego miałbyś to umieścić w pętli while? Proszę rozwinąć i wyjaśnić swoją odpowiedź.
Uberhumus