Получение curl для вывода кода состояния HTTP?

799

Я использую curlв командной строке в Linux для выдачи HTTP-запросов. Тела ответа печатаются в стандартном формате, и это нормально, но я не вижу на странице руководства, как заставить curl печатать код состояния HTTP из ответа (404, 403 и т. Д.). Это возможно?

КДТ
источник
Что касается меня, я могу видеть из руководства, как получить код состояния HTTP, но опция -w не работает. Я сообщил об ошибке в Apple.
Николас Барбулеско
19
-iФлаг, как curl -i https://www.example.com/, вероятно , что вы хотите, согласно superuser.com/a/514798/190188
каркать
Почему не просто что-то вроде curl -IL http://www.example.com | grep "^HTTP\/"?
St3an
Не для будущего себя: ответ, который вы хотите, вероятно, Кирилл Дэвид (в настоящее время на 4-й позиции)
WhiteHotLoveTiger

Ответы:

525

Это должно работать для вас, если веб-сервер может отвечать на запросы HEAD (это не будет выполнять a GET):

curl -I http://www.example.org

Кроме того, чтобы позволить cURL следовать перенаправлениям (статусы 3xx), добавьте -L.

pberlijn
источник
155
NB: curl -Iвыполняет HTTP-запрос HEAD, который может быть проблематичным для тестирования кода состояния HTTP для некоторых серверов и служб веб-приложений
Джей Тейлор,
16
И чтобы получить только номер статуса, head -n 1|cut -d$' ' -f2
отправьте
33
Не забудьте перенаправить поток ошибок Curl в: curl -I http://www.example.org 2>/dev/null | head -n 1 | cut -d$' ' -f2. Добавьте -L в curl, если вам нужен окончательный статус после перенаправления.
Аарон Бленкуш
1
После перенаправления только после выполнения запроса HEAD может возникнуть интересное поведение в зависимости от того, как запрограммировано приложение.
Скотт Макинтайр
32
curl -I -X GETотправит запрос GET, но даст тот же результат.
Джигги
837

Более конкретный способ распечатать только код состояния HTTP - это что-то вроде:

curl -s -o /dev/null -w "%{http_code}" http://www.example.org/

Намного проще работать в скриптах, так как это не требует синтаксического анализа :-)

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

Примечание: %{http_code} возвращается в первую строку полезной нагрузки HTTP

то есть:

curl -s -o /dev/null -I -w "%{http_code}" http://www.example.org/
pvandenberk
источник
54
-w "% {http_code}" - это бит, который печатает код состояния. Вы можете добавить новую или две строки там, чтобы отделить код от тела (-w "\ n \ n% {http_code} \ n")
Джеффри Мартинес
7
Вау, эта /dev/nullштука работает даже в Windows-версии curl, которую я использую.
Уве Кейм
3
Я считаю, что это загружает весь файл, хотя все это идет в / dev / null, поэтому не идеально подходит для проверки кода состояния для больших файлов. httping -c 1 -s -G -mвыдает GET и не загружает весь файл, хотя я понимаю, что этот вопрос специально о curl.
RomanSt
40
К вашему сведению: -s= не показывать ход загрузки, -o /dev/null= не отображать тело, -w "%{http_code}"= записывать код ответа http в стандартный вывод после выхода.
Ajedi32
1
Обязательны ли кавычки вокруг "% {http_code}"?
Хакан Баба
217

Если вы хотите увидеть заголовок и результат, вы можете использовать подробную опцию:

curl -v http://www.example.org
curl --verbose http://www.example.org

Статус появится в шапке. Например

< Date: Tue, 04 Nov 2014 19:12:59 GMT
< Content-Type: application/json; charset=utf-8
< Status: 422 Unprocessable Entity
Энрико Сусатио
источник
26
+1 за указание на подробный флаг предоставляет дополнительную информацию. Отлично подходит для тестирования REST-приложений.
MrOodles
8
+1 очень прост в использовании при выполнении запроса POST (curl -v --data "...")
MegaTux
1
Он даже разделяет их на два разных выходных файла (подробности статуса http для stderr и тело ответа для stdout)
phil294
201

Вы можете напечатать код состояния в дополнение ко всем заголовкам, выполнив следующие действия:

curl -i http://example.org

Хорошая вещь о -iтом, что это работает с -X POST.

Кирилл Давид
источник
36
Гораздо лучше, чем принятый ответ (который делает запрос HEAD).
neu242
10
Может быть, очевидно, но -iработает с любым методом HTTP, не только GETи POST... :)
mac
3
лучший ответ, поскольку он делает вывод curl как заголовками, так и телом, что делает его пригодным для большинства задач при использовании в скрипте
Sarge Borsch
6
Это лучший ответ, и его можно использовать вместе с -s(не показывать индикатор прогресса или сообщения об ошибках) и -S(показывать сообщения об ошибках в конце концов)
Джонатан Хартли
69

Если вы хотите записать код состояния HTTP в переменную, но по-прежнему перенаправлять содержимое в STDOUT, необходимо создать два STDOUT. Вы можете сделать это с подстановкой процесса> () и подстановкой команды $ () .

Сначала создайте файловый дескриптор 3для текущего процесса 'STDOUT с exec 3>&1.

Затем используйте параметр curl, -oчтобы перенаправить содержимое ответа во временный fifo с помощью подстановки команд, а затем в рамках этой подстановки команд перенаправить вывод обратно в дескриптор файла текущего процесса STDOUT 3с помощью -o >(cat >&3).

Собираем все вместе в bash 3.2.57(1)-release(стандарт для macOS):

# creates a new file descriptor 3 that redirects to 1 (STDOUT)
exec 3>&1 
# Run curl in a separate command, capturing output of -w "%{http_code}" into HTTP_STATUS
# and sending the content to this command's STDOUT with -o >(cat >&3)
HTTP_STATUS=$(curl -w "%{http_code}" -o >(cat >&3) 'http://example.com')

Обратите внимание, что это не работает, /bin/shкак SamK отметил в комментариях ниже .

Хит Границы
источник
5
Это серьезное занудство ... и мне это нравится!
spyle
3
Теперь, как, в свою очередь, я могу перенаправить вывод в другую переменную?
Роджер Фильмьер
1
Вывод находится в STDOUT, так что вы должны иметь возможность перенаправить вывод из команды куда угодно, как обычная команда. Я не проверял это все же.
Хит Границы
1
Не работает с / bin / sh.
SamK
Хороший ответ, вы также можете перенаправить на реальный файл и
отследить
32

Переопределить вывод curl:

curl -sw '%{http_code}' http://example.org

Может использоваться с любым типом запроса.

Grzegorz Luczywo
источник
-k (--insecure) переопределяет -s (молчит).
Равичандра
16

ТОЛЬКО код состояния

[0]$ curl -LI http://www.example.org -o /dev/null -w '%{http_code}\n' -s
[0]$ 200

Все заслуги в этом GIST

mahatmanich
источник
11

Это болезненное curl --failограничение. От man curl:

-f, --fail (HTTP) Fail молча (без вывода вообще) при ошибках сервера

Но нет способа получить и ненулевой код возврата, и тело ответа в stdout.

Основываясь на ответе pvandenberk и этом другом очень полезном трюке, изученном на SO , вот обходной путь:

curl_with_error_code () {
    _curl_with_error_code "$@" | sed '$d'
}
_curl_with_error_code () {
    local curl_error_code http_code
    exec 17>&1
    http_code=$(curl --write-out '\n%{http_code}\n' "$@" | tee /dev/fd/17 | tail -n 1)
    curl_error_code=$?
    exec 17>&-
    if [ $curl_error_code -ne 0 ]; then
        return $curl_error_code
    fi
    if [ $http_code -ge 400 ] && [ $http_code -lt 600 ]; then
        echo "HTTP $http_code" >&2
        return 127
    fi
}

Эта функция ведет себя точно так же curl, но вернет 127 (код возврата не используется curl) в случае HTTP-кода в диапазоне [400, 600 [.

Лукас Кимон
источник
Согласитесь, невозможность увидеть вывод ошибки - болезненное ограничение в противном случае очень полезного --fail. Как можно диагностировать сбой REST API, не видя вывод ошибки? Это так прискорбно, что специалист по обслуживанию локонов упрямо настаивает на том, чтобы не выдавать ошибку «с ошибкой, но с шоу». github.com/curl/curl/issues/1978
Джамшид
Как указано в документации, он не работает для HTTP-кода 401 и 407 :(
Логан Мзз
11

Это отправит запрос на URL, получит только первую строку ответа, разделит его на блоки и выберет вторую.

Содержит код ответа

curl -I http://example.org 2>/dev/null | head -n 1 | cut -d$' ' -f2
Филипп Спиридонов
источник
1
Можете ли вы объяснить, что делает этот код и как он решает проблему, заданную ФП? Необъяснимый код может показаться ненадежным и опасным для пользователей.
BwDraco
1
Конечно, мы отправляем запрос на URL, получаем только первую строку ответа, разбиваем его на блоки и выбираем вторую. Он содержит код ответа, который ищет OP.
Филипп Спиридонов
9

Для запроса POST сработало следующее:

curl -w 'RESP_CODE:%{response_code}' -s -X POST --data '{"asda":"asd"}' http://example.com --header "Content-Type:application/json"|grep -o  'RESP_CODE:[1-4][0-9][0-9]'
zafar142003
источник
6

Используйте следующую команду cURL и передайте ее в grep следующим образом:

$ curl -I -s -L http://example.com/v3/get_list | grep "HTTP / 1.1"

Вот что делает каждый флаг:

  • -I: Показать только заголовки ответа
  • -s: Silent - не показывать индикатор выполнения
  • -L: Следуйте Location:заголовкам

Вот ссылка на коды состояния HTTP .

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

Савитой Сингх
источник
5
curl -so -i /dev/null -w "%{http_code}"  http://www.any_example.com

Это вернет следующую информацию:

  1. данные ответа, если какие-либо данные возвращаются API, как ошибка
  2. код состояния
srana
источник
Это не следует за перенаправлениями. Этот существующий ответ лучше superuser.com/a/442395/475508
cricket_007
Конечно, вы также можете сослаться на это !!
Срана
4

Вот некоторая команда curl, которая использует GETи возвращает код HTTP.

curl -so /dev/null -w '%{response_code}' http://www.example.org

Пожалуйста, помните, что используется приведенный ниже подход HEAD, который работает быстрее, но он может не работать с некоторыми менее веб-HTTP-серверами.

 curl -I http://www.example.org
Сорин
источник
Не работает на OS X по крайней мере.
Айн
Работает нормально для меня на OS X High Sierra 10.13.6.
Бен Барон
4

Пример использования кодов ответов. Я использую это для повторной загрузки баз Geolite, только если они изменились ( -z), а также после перенаправлений ( -L):

url=http://example.com/file.gz
file=$(basename $url)

response=$(curl -L -s -o $file -z $file $url -w "%{http_code}")

case "$response" in
        200) do_something ;;
        301) do_something ;;
        304) printf "Received: HTTP $response (file unchanged) ==> $url\n" ;;
        404) printf "Received: HTTP $response (file not found) ==> $url\n" ;;
          *) printf "Received: HTTP $response ==> $url\n" ;;
esac
Стюарт Кардалл
источник
3

ОП хочет знать код статуса. Часто при загрузке файла вы также хотите почувствовать его размер, поэтому я сначала использую curl, чтобы показать код состояния и размер файла, а затем отключить подробный и направить файл в нужное место и имя:

curl -R -s -S -w  "\nhttp: %{http_code} %{size_download}\n" -o /Users/myfiles/the_local_name.html http://archive.onweb.com/the_online_name.html

Потом жду финиша скручивания

wait ${!}

перед тем, как запустить следующую команду. Выше, когда используется в сценарии многих команд, как выше, дает хороший ответ, как:

http: 200 42824

http: 200 34728

http: 200 35452

Обратите внимание, что -o в curl должен сопровождаться полным путем файла + именем файла. Таким образом, это позволяет вам сохранять файлы с разумной структурой имен, когда вы добавляете их с помощью curl. Также обратите внимание, что -s и -S, используемые вместе, отключают вывод, но показывают ошибки. Также обратите внимание, что -R пытается установить временную метку файла для веб-файла.

Мой ответ основан на том, что первоначально предложил @pvandenberk, но кроме того, он фактически сохраняет файл где-то, а не просто указывает на / dev / null.

sakumatto
источник
1

Разделить выводимое содержимое на stdoutи код состояния HTTP на stderr:

curl http://www.example.org -o >(cat >&1) -w "%{http_code}\n" 1>&2

Если для stderr требуется только HTTP-код состояния, --silentможно использовать:

curl --silent http://www.example.org -o >(cat >&1) -w "%{http_code}\n" 1>&2

Затем можно выбрать нужный поток, перенаправив нежелательный поток на /dev/null:

$ (curl --silent http://www.example.org -o >(cat >&1) -w "%{http_code}" 1>&2) 1>/dev/null
200
$ (curl --silent http://www.example.org -o >(cat >&1) -w "%{http_code}" 1>&2) 2>/dev/null
<!doctype html>
...

Обратите внимание, что для второго перенаправления нужно вести себя как нужно, нам нужно запустить команду curl в subshell.

Jaakko
источник
1
Требуется bashдля процесса замены.
Яакко
@ Bruno, я изменил пример с superuser.com/revisions/1444693/2 , так как я думаю, что /tmp/out /tmp/errфайлы могут привести к неожиданным результатам при параллельной работе.
Яакко