我正在观看有趣的服务器类型http://www.reddit.comcurl -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
知道为什么会出现这种行为差异吗?
答案1
看起来差异与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(自己尝试一下)标题:)。
答案2
我认为这是 curl 的一个错误。如果我使用 -X 指定方法,curl 应该根据 RFC 处理响应。不幸的是,curl 的维护者不同意。有人提交了一个错误,甚至提交了一个补丁:
http://sourceforge.net/tracker/?func=detail&atid=100976&aid=1810273&group_id=976
但 curl 维护者拒绝了它。显然,损坏的“-X HEAD”选项“按设计工作”。
--贾姆希德
答案3
从文档:
-X,--请求
(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
答案4
我在 curl 7.34 上编写 cpp 代码时遇到了同样的问题,
curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "HEAD");
会挂在那里很长时间,似乎在等待主体传输,直到超时。添加新行后,此问题得到解决。
curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1L );
从文档
执行下载请求而不获取主体
此行将强制 curl 不再等待。