Разница между `curl -I` и` curl -X HEAD`

70

Я смотрел забавный тип сервера с http://www.reddit.com с, curl -I http://www.reddit.comкогда я догадался, что curl -X HEAD http://www.reddit.comбудет то же самое. Но на самом деле это не так.

Мне интересно, почему.

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

  • curl -I: работает как положено, выводит заголовок и существует.

  • curl -X HEAD: ничего не показывает и, кажется, ждет ввода пользователя.

Но, нюхая, tsharkя вижу, что вторая команда фактически отправляет тот же HTML-запрос и получает правильный ответ, но он не показывает его и не закрывает соединение.

curl -I

0.000000 333.33.33.33 -> 213.248.111.106 TCP 59675 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=47267342 TSER=0 WS=6
0.045392 213.248.111.106 -> 333.33.33.33 TCP http > 59675 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2552532839 TSER=47267342 WS=1
0.045441 333.33.33.33 -> 213.248.111.106 TCP 59675 > http [ACK] Seq=1 Ack=1 Win=5888 Len=0 TSV=47267353 TSER=2552532839
0.045623 333.33.33.33 -> 213.248.111.106 HTTP HEAD / HTTP/1.1
0.091665 213.248.111.106 -> 333.33.33.33 TCP http > 59675 [ACK] Seq=1 Ack=155 Win=6432 Len=0 TSV=2552532886 TSER=47267353
0.861782 213.248.111.106 -> 333.33.33.33 HTTP HTTP/1.1 200 OK
0.861830 333.33.33.33 -> 213.248.111.106 TCP 59675 > http [ACK] Seq=155 Ack=321 Win=6912 Len=0 TSV=47267557 TSER=2552533656
0.862127 333.33.33.33 -> 213.248.111.106 TCP 59675 > http [FIN, ACK] Seq=155 Ack=321 Win=6912 Len=0 TSV=47267557 TSER=2552533656
0.910810 213.248.111.106 -> 333.33.33.33 TCP http > 59675 [FIN, ACK] Seq=321 Ack=156 Win=6432 Len=0 TSV=2552533705 TSER=47267557
0.910880 333.33.33.33 -> 213.248.111.106 TCP 59675 > http [ACK] Seq=156 Ack=322 Win=6912 Len=0 TSV=47267570 TSER=2552533705

curl -X HEAD

34.106389 333.33.33.33 -> 213.248.111.90 TCP 51690 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=47275868 TSER=0 WS=6
34.149507 213.248.111.90 -> 333.33.33.33 TCP http > 51690 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=3920268348 TSER=47275868 WS=1
34.149560 333.33.33.33 -> 213.248.111.90 TCP 51690 > http [ACK] Seq=1 Ack=1 Win=5888 Len=0 TSV=47275879 TSER=3920268348
34.149646 333.33.33.33 -> 213.248.111.90 HTTP HEAD / HTTP/1.1
34.191484 213.248.111.90 -> 333.33.33.33 TCP http > 51690 [ACK] Seq=1 Ack=155 Win=6432 Len=0 TSV=3920268390 TSER=47275879
34.192657 213.248.111.90 -> 333.33.33.33 TCP [TCP Dup ACK 15#1] http > 51690 [ACK] Seq=1 Ack=155 Win=6432 Len=0 TSV=3920268390 TSER=47275879
34.823399 213.248.111.90 -> 333.33.33.33 HTTP HTTP/1.1 200 OK
34.823453 333.33.33.33 -> 213.248.111.90 TCP 51690 > http [ACK] Seq=155 Ack=321 Win=6912 Len=0 TSV=47276048 TSER=3920269022

Есть идеи о том, почему такая разница в поведении?

chmeee
источник
1
См. Также daniel.haxx.se/blog/2015/09/11/unneeded-use-of-curl-x
Аббафей

Ответы:

66

Кажется, разница связана с Content-Lengthзаголовком и тем, как он обрабатывается обеими командами.

Но перед этим curl -X HEADне выдает никаких выходных данных, потому что по умолчанию curlне печатает заголовки, если переключатель -iне предусмотрен ( -Iхотя он и не нужен ).

В любом случае, curl -Iэто правильный способ получить заголовки. Это просто попросить заголовок и закрыть соединение.

С другой стороны, curl -X HEAD -iбудет ожидать передачи числа байтов, указанного Content-Length. В случае, если нет Content-Lengthне указано, я думаю, он будет ждать некоторые данные или для этого конкретного заголовка.

Некоторые примеры, демонстрирующие это поведение:

$ curl -X HEAD -i http://www.elpais.es
HTTP/1.1 301 Moved Permanently
Server: AkamaiGHost
Content-Length: 0
Location: http://www.elpais.com/
Date: Wed, 12 May 2010 06:35:57 GMT
Connection: keep-alive

Поскольку Content-Lengthэто 0, в этом случае обе команды ведут себя одинаково. И связь закрыта впоследствии.

$ curl -X HEAD -i http://slashdot.org
HTTP/1.1 200 OK
Server: Apache/1.3.41 (Unix) mod_perl/1.31-rc4
SLASH_LOG_DATA: shtml
X-Powered-By: Slash 2.005001296
X-Bender: Since I love you all so much, I'd like to give everyone hugs.
X-XRDS-Location: http://slashdot.org/slashdot.xrds
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=iso-8859-1
Content-Length: 115224
Date: Wed, 12 May 2010 06:37:20 GMT
X-Varnish: 1649060825 1649060810
Age: 1
Connection: keep-alive

curl: (18) transfer closed with 115224 bytes remaining to read

В этом случае, похоже, истекло время ожидания (вероятно, от Varnish), поэтому curlпротестует, что соединение было закрыто до получения Content-Lengthколичества байтов.

Кстати, посмотрите на забавные заголовки X-Bender (показано в примере) и X-Fry (попробуйте сами) :).

chmeee
источник
2
В случае, если кто-то еще ищет это: опция для установки в библиотеке curl PHP есть CURLOPT_NOBODY.
Мэтью
12

Я думаю, что это ошибка в curl. Если я указываю метод с -X, curl должен обрабатывать ответ в соответствии с RFC. К сожалению, сопровождающий curl не согласен. Кто-то подал ошибку и даже представил патч:

http://sourceforge.net/tracker/?func=detail&atid=100976&aid=1810273&group_id=976

но хранитель локонов отверг это. Видимо, неработающая опция "-X HEAD" - это "работа, как задумано".

--Jamshid

Джамшид
источник
4
Честно говоря, я могу следовать логике ответа на тикет: --headон предоставляет нам правильную реализацию HEAD-запроса и -X <method>просто переопределяет HTTP-метод в запросе.
Хэнк
3
да, это было на самом деле то, что мне было нужно. У меня есть глючный сервер, который обслуживает контент при получении запроса HEAD. -X HEADэто был единственный способ, которым я мог проверить это, пытаясь заставить сервер придерживаться RFC
Hashbrown
5

Из документов :

-X, --request

(HTTP) Определяет пользовательский метод запроса, который будет использоваться при взаимодействии с HTTP-сервером. Указанный метод запроса будет использоваться вместо метода, который используется в противном случае (по умолчанию используется GET). Прочитайте спецификацию HTTP 1.1 для деталей и объяснений. Обычные дополнительные HTTP-запросы включают PUT и DELETE, но связанные технологии, такие как WebDAV, предлагают PROPFIND, COPY, MOVE и другие.

Обычно вам не нужна эта опция. Все виды запросов GET, HEAD, POST и PUT скорее вызываются с помощью специальных параметров командной строки.

Эта опция только изменяет фактическое слово, используемое в HTTP-запросе, но не меняет поведение curl . Так, например, если вы хотите сделать правильный запрос HEAD, использование -X HEAD будет недостаточно. Вам нужно использовать опцию -I, --head.

Другими словами, -Xдля других , чем методы GET, HEAD, POSTи PUT. Для HEADиспользования -I.

х-юри
источник
0

Я сталкиваюсь с той же проблемой при написании кода cpp на curl 7.34,

curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "HEAD");

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

curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1L );

из документа

сделать запрос на скачивание без получения тела

эта линия заставит локон не ждать.

dasons
источник