NSURLConnection uses GET even when I ask for HEAD

Originator:boredzo
Number:rdar://7019347 Date Originated:2009-06-30T02:57-0700
Status:Open Resolved:
Product:Mac OS X Product Version:10.5.7/9J61
Classification:Other Bug Reproducible:Always
 
Summary:
Even when the caller sets the request's HTTP method to HEAD, NSURLConnection uses GET to retrieve the resource.

Steps to Reproduce:
1. Create an NSURLRequest for an HTTP URL.
2. Set its HTTP method to @"HEAD".
3. Create an NSURLConnection for the request, and start it immediately.

Expected Results:
The NSURLConnection uses HEAD to obtain a basic response with no body, and does not send connection:didReceiveData: to its delegate.

Actual Results:
The NSURLConnection uses GET, and sends connection:didReceiveData: to its delegate.

Regression:
Unknown.

Workaround:
One is to cancel and release the connection in connection:didReceiveResponse: or connection:didReceiveData:. Another is to set a Range header of “bytes=0-1” on the request, but that probably won't work for all resources. (Latter workaround suggested by Mo (@nevali) on Twitter.)

Notes:
HTTP 1.1 explicitly requires HEAD to not return a body. I confirmed using curl that the server I was testing with was not returning a body. However, my Cocoa app's connection delegate does receive a body. Therefore, the connection must be using GET (I'm assuming it's not using POST).

It doesn't matter whether I use the synchronous or asynchronous API. The synchronous API returns an empty data object, but I can tell by looking at network traffic that it is downloading the file.

I wrote a test app using the asynchronous API:

	https://bitbucket.org/boredzo/http-header-retriever/

	Zip archive of source that's current as I write this:
	https://bitbucket.org/boredzo/http-header-retriever/get/0b3d8cbe5db2.zip

	Zip archive of whatever source is current when you download it:
	https://bitbucket.org/boredzo/http-header-retriever/get/tip.zip

After you enter a URL and hit Retrieve in the app's main window, switch over to Xcode and take a look at the Run Log.

Comments

Have You Checked Redirects?

Are you sure this isn’t because the URL you’re using has redirects? If it uses redirects, you have to update the method for the redirect.

I’ve already fixed a problem like this in an older version of ClickToFlash.

Good point— I just fixed a similar bug with HEAD requests in a local app (by implementing -connection:willSendRequest:redirectResponse: appropriately). Tcpdump showed that it was in fact sending the HEAD at first but switching to GET after a redirect.

The HTTP RFC discusses this behavior a bit: see RFC2616 section 10.3, especially the notes in sections 10.3.2 and 10.3.3.


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!