Difference between `curl -I` and `curl -X HEAD`

Solution 1:

It seems the difference has to do with the Content-Length header and how it is treated by both commands.

But before going into that, curl -X HEAD does not give any output because, by default, curl does not print headers if switch -i is not provided (not needed on -I though).

In any case, curl -I is the proper way to fetch the headers. It just ask for the header and close the connection.

On the other hand curl -X HEAD -i will wait for the transmission of the number of bytes stated by Content-Length. In the case no Content-Length is not specified, I guess it will wait for some data or for that particular header.

Some examples that shows this behaviour:

$ 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

Because Content-Length is 0, in this case both commands behave the same. And the connection is closed afterwards.

$ 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

In this case, there seems to be a timeout (probably by Varnish), so curl protests that the connection was closed before having received the Content-Length number of bytes.

By the way, look at the funny X-Bender (shown in the example) and X-Fry (try it for yourself) headers :).

Solution 2:

I think this is a bug in curl. If I specify a method with -X, curl should handle the response according to the RFC. Unfortunately, the maintainer of curl does not agree. Someone filed a bug and even submitted a patch:

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

but the curl maintainer rejected it. Apparently a broken "-X HEAD" option is "working as designed".

--Jamshid


Solution 3:

From the docs:

-X, --request

(HTTP) Specifies a custom request method to use when communicating with the HTTP server. The specified request method will be used instead of the method otherwise used (which defaults to GET). Read the HTTP 1.1 specification for details and explanations. Common additional HTTP requests include PUT and DELETE, but related technologies like WebDAV offers PROPFIND, COPY, MOVE and more.

Normally you don't need this option. All sorts of GET, HEAD, POST and PUT requests are rather invoked by using dedicated command line options.

This option only changes the actual word used in the HTTP request, it does not alter the way curl behaves. So for example if you want to make a proper HEAD request, using -X HEAD will not suffice. You need to use the -I, --head option.

In other words, -X is for methods other than GET, HEAD, POST and PUT. For HEAD use -I.