CURLHandle 3.0

In the beginning there was NSURLHandle. And it was … ok. It was easy to load URLs, even asynchronously (gasp!).

But it was rather limited and a little buggy; there was no finer control to be gained over the nuances of HTTP. And so in 2001, Dan created CURLHandle to wrap NSURLHandle's API around libcurl for use in Watson. And the people were happy.

With the release of Safari (on OS X 10.2), Foundation gained a brand new collection of classes — the URL Loading System. Chief of these was NSURLConnection, taking on the majority of NSURLHandle's role. Between it, NSURLRequest and NSHTTPURLResponse, quite a lot could be done with HTTP. There was even NSURLDownload for convenient resumable download support.

The uses for CURLHandle had lessened.

Apple's engineers continued to toil. OS X 10.4 brought with it support for streamed HTTP requests. NSURLHandle was officially deprecated.

OS X 10.6 brought a delegate method to inform of upload progress. And with that it seemed CURLHandle had served its time. NSURLConnection now handled pretty much all the use cases.

So why then would we resurrect CURLHandle for version 3? Sandvox uses ConnectionKit for its FTP support. Unfortunately, the implementation is a bit buggy, and monstrously hard to follow for debugging. How could this be improved upon?

NSURLConnection and CFNetwork both feature built-in FTP support, but it has pretty strict limits. Beyond their prescribed operations of downloading files and directory listings, and uploading files, nothing more can be done. It doesn't make sense to use a mixture of implementations (they'd have to maintain their own separate connections to the server for a start), so something else needed to be found.

Happily libcurl features a mature FTP implementation, albeit behind a slightly obtuse API. So I battled on and retooled CURLHandle for the modern age:

  • The API now deals in terms of NSURLRequest, supporting pretty much all of the standard HTTP settings
  • The implementation is entirely synchronous. Older versions faked being async by performing the work on a background thread. If you still want to do this, GCD makes it a breeze
  • There's also NSURLConnection support via CURLProtocol. Simply call -setShouldUseCurlHandle:YES when creating requests
  • Most important of all, CURLFTPSession provides an NSFileManager-like API for performing FTP operations

We're using it in Sandvox today by default, and it's been working pretty well. Sound like something you want too? Or wish to contribute? Head over to GitHub for the code.

© Mike Abdullah 2007-2015