Curl для возврата кода статуса http вместе с ответом


119

Я использую curl для получения заголовков http, чтобы найти код статуса http, а также вернуть ответ. Я получаю заголовки http с помощью команды

curl -I http://localhost

Чтобы получить ответ, я использую команду

curl http://localhost

Как только я использую флаг -I, я получаю только заголовки, а ответа больше нет. Есть ли способ получить как ответ http, так и код состояния заголовков / http в одной команде?


1
Вот очень полезный сниппет gist.github.com/maxcnunes/9f77afdc32df354883df
rocketspacer

Ответы:


116

Я смог найти решение, посмотрев на документ curl, в котором указано, что нужно использовать -для вывода, чтобы получить вывод на стандартный вывод.

curl -o - http://localhost

Чтобы получить ответ только с кодом возврата http, я мог бы просто сделать

curl -o /dev/null -s -w "%{http_code}\n" http://localhost

15
или вы бы использовали -i. Или, возможно -v, вам нужна дополнительная информация.
Дэниел Стенберг,

2
Спасибо @DanielStenberg. Принятый ответ не сработал для меня, просто сработало -i.
Алехандро

ваша вторая команда отсутствует -I @randominstanceOfLivingThing, если это не намеренно пустой параметр? У меня без него не работает
mdo123 05

2
-o -Iзаканчивается созданием файла с буквальным названием ' -I' в CWD. Кто-нибудь еще это видит? Решение для этого-o/dev/null -I
JDS

Удален -I. Заметил и поправил сейчас. Вам не нужен -I.
randominstanceOfLivingThing


39

Я использую эту команду для печати кода состояния без каких-либо других выходных данных. Кроме того, он будет выполнять только запрос HEAD и следовать перенаправлению (соответственно -Iи -L).

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

Это позволяет очень легко проверить код состояния в сценарии работоспособности:

sh -c '[ $(curl -o -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]'

5
На это уже был дан ответ год назад. Какую новую ценность приносит ваш ответ? Также напишите пояснение к вашему ответу.
Maciej Jureczko 01

11
@MaciejJureczko - Ценность проста. Для целей сценариев этот ответ является лучшим из всех других ответов, потому что он дает один код состояния вместо множества строк мусора вместе с указанным кодом состояния.
aggregate1166877

2
Но OP конкретно заявляет, что им нужен как код состояния, так и тело ответа. Они знают, как просто получить код ответа (указанный в вопросе)
wottle

2
Всякий раз, когда я использую это, curl -o -I -L -s -w "%{http_code}" http://localhostсоздается файл с именем -I, чтобы обойти это, я добавил место для вывода файла, подразумеваемого -oto go, а именно /dev/null:curl -o /dev/null -I -L -s -w "%{http_code}" http://localhost
Thismatters

HEAD не всегда приводит к тому же результату, что и запрос, до ответа сервера. Так что это не совсем ответ.
Эдди

28

Я нашел этот вопрос, потому что мне нужен ОБА ответ и контент, чтобы добавить некоторую обработку ошибок для пользователя.

Вы можете распечатать код состояния HTTP на стандартный вывод и записать содержимое в другой файл.

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

Это позволяет вам использовать логику, чтобы решить, стоит ли обрабатывать ответ.

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

что такое http_code? Я этого не понимаю, нужны дополнительные объяснения, пожалуйста,
Александр Миллс

Как пояснено выше, это относится к коду состояния HTTP - developer.mozilla.org/en-US/docs/Web/HTTP/Status
Эдди

24

-iВариантом является тот , который вы хотите:

curl -i http://localhost

-i, --include Включить заголовки протокола в вывод (H / F)

В качестве альтернативы вы можете использовать подробный вариант:

curl -v http://localhost

-v, --verbose Сделать операцию более разговорчивой


16

Я использовал это:

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

Чтобы получить статус HTTP

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

Чтобы получить тело ответа, я использовал это

    output_response=$(echo "$request_cmd" | grep body)
    echo $output_response

8

Эта команда

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

получит тело и статус, разделенные запятыми; вы можете разделить их, чтобы вытащить.

Вы можете изменить разделитель по своему усмотрению.


2
хороший намек! можно ли добавить код состояния перед выводом?
Psychozoic

6

Для программного использования я использую следующее:

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

Он показывает следующий вывод:

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

5

Это способ получить тело «И» с кодом состояния и отформатировать его в правильный json или любой другой формат, который вам подходит. Кто-то может возразить, что это неправильное использование параметра формата записи, но это работает для меня, когда мне нужен как основной код, так и код состояния в моих сценариях, чтобы проверить код состояния и передать ответы с сервера.

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

запустите приведенный выше код, и вы должны получить обратно json в этом формате:

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

с параметром -w write format, поскольку сначала печатается stderr, вы можете отформатировать вывод с помощью var http_code и поместить тело ответа в значение (body), а затем выполнить включение с помощью var stdout. Затем перенаправьте свой вывод stderr на stdout, и вы сможете объединить как http_code, так и тело ответа в аккуратный вывод


1
curl: unknown --write-out variable: 'stderr'curl: unknown --write-out variable: 'stdout'
Получена

curl.haxx.se/docs/manpage.html справочная страница показывает доступные переменные. Не уверен, почему stderr не распознается вашим завитком, завитком на MacBook. Из этого документа Linux curl, computerhope.com/unix/curl.htm , я тоже не вижу stderr как переменную. Возможно, это вариация ОС.
Хай Тран,

Единственная проблема, с которой я сталкиваюсь, - это если у вашего тела есть кавычки, например, если его json, тело сделает ответ json выше недопустимого json
диктор

честно @theannouncer, я ожидаю, что разработчик внесет соответствующие изменения, так как не все ответы будут стандартными json. Были некоторые случаи, когда мне приходилось приспосабливаться из-за характера ответа.
Huy Tran,

2

Мой способ добиться этого :

Чтобы получить и то, и другое (заголовок и тело), ​​я обычно выполняю следующее curl -D- <url>:

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

Это сбрасывает headers ( -D) в stdout ( -) (ищите --dump-headerв man curl ).

ИМХО тоже очень удобно в этом контексте:

Я часто использую jq для форматирования данных json (например, из некоторых остальных API). Но поскольку jq не ожидает HTTP-заголовка, хитрость заключается в том, чтобы напечатать заголовки в stderr, используя -D/dev/stderr. Обратите внимание, что на этот раз мы также используем -sS(--silent, --show-errors) для подавления индикатора выполнения (потому что мы пишем в канал).

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

Я думаю, это также может быть удобно, если вы хотите распечатать заголовки (для быстрой проверки) на консоли, но перенаправить тело в файл (например, когда это какой-то двоичный файл, чтобы не испортить ваш терминал):

$ 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

Имейте в виду: это НЕ то же самое, что curl -I <url>! As -Iбудет выполнять HEADзапрос, а не GETзапрос (ищите --headв man curl . Да: для большинства HTTP-серверов это даст тот же результат. Но я знаю множество бизнес-приложений, которые вообще не реализуют HEADзапросы ;-P


0

Добавьте строку «http_code: 200» в конце, а затем используйте grep для ключевого слова «http_code:» и извлеките код ответа.

result=$(curl -w "\nhttp_code:%{http_code}" http://localhost)

echo "result: ${result}"   #the curl result with "http_code:" at the end

http_code=$(echo "${result}" | grep 'http_code:' | sed 's/http_code://g') 

echo "HTTP_CODE: ${http_code}"  #the http response code

В этом случае вы все равно можете использовать немой режим / подробный режим, чтобы получить дополнительную информацию о запросе, например о теле ответа curl.


-2
while : ; do curl -sL -w "%{http_code} %{url_effective}\\n" http://host -o /dev/null; done

1
Зачем вам вставлять это в цикл while? Пожалуйста, расширьте и объясните свой ответ.
Uberhumus,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.