TestsTested | ✗ |
LangLanguage | Obj-CObjective C |
License | Apache 2 |
ReleasedLast Release | Dec 2014 |
Maintained by Unclaimed.
BBHTTP is a rich wrapper for libcurl written in Objective-C.
It is an ARC-only library that uses features introduced by Clang 3.1. Thus, it is only suitable for iOS 5+ and OSX 10.7+.
It boasts an extremely simple and compact interface that allows you to reduce your code to fire off HTTP requests down to a couple of clean lines, while preserving full flexibility should you ever need it.
[[BBHTTPRequest getResource:@"http://foo.bar/baz"] execute:^(BBHTTPResponse* r) {
NSLog(@"Finished: %u %@ -- received %u bytes of '%@'.",
r.code, r.message, r.contentSize, r[@"Content-Type"]);
} error:^(NSError* e) {
NSLog(@"Request failed: %@", [e localizedDescription]);
}];
// Finished: 200 OK -- received 68364 bytes of 'text/html'.
At this stage there are still a lot of rough edges to polish, bugs to fix and features missing to bring it up-to-par with other similar projects. I want to add those over time but help is always more than welcome so be sure to open issues for the features you'd love to see or drop me a mention @biasedbit on Twitter.
The API is very likely to keep mutating until this reaches 1.0.
Concise asynchronous-driven usage:
[[BBHTTPRequest deleteResource:@"http://foo.bar/baz/1"] execute:^(BBHTTPResponse* r) {
// handle response
} error:nil]];
You don't even need to keep references to the requests, just fire and forget.
Handy common usage patterns:
[[BBHTTPRequest getResource:@"http://foo.bar/baz/1"] setup:^(id request) {
// Prepare request...
} execute:^(BBHTTPResponse* response) {
// Handle response...
} error:^(NSError* error) {
// Handle error...
} finally:^{
// Do after error OR success.
}];
* Get JSON effortlessly:
```objc
[[[BBHTTPRequest getResource:@"http://foo.bar/baz.json"] asJSON] execute:^(BBHTTPResponse* r) {
NSLog(@"User email: %@", r.content[@"user.email"]);
NSLog(@"# of followers: %@", r.content[@"user.followers.@count"]);
} error:^(NSError* error) {
// Handle request *or* JSON decoding error
}];
Notice the keyed subscript operator behaves as
valueForKeyPath:
rather thanvalueForKey:
. That's because JSON responses that would yield aNSDictionary
get wrapped byBBJSONDictionary
. Read more about the collection operators here.
[[BBHTTPRequest getResource:@"http://foo.bar/baz.png"] setup:^(id request) {
[request downloadContentAsImage];
} execute:^(BBHTTPResponse* response) {
UIImage* image = response.content; // NSImage on OSX
NSLog(@"image size: %@", NSStringFromCGSize(image.size));
} error:nil];
This example uses
downloadContentAsImage
on thesetup
block to setup the image download & conversion but you could also use the fluent syntax alternative (asImage
), just like on the JSON example above.
NSInputStream
or directly from a file:[[BBHTTPRequest createResource:@"http://foo.bar/baz" withContentsOfFile:@"/path/to/file"]
setup:^(BBHTTPRequest* request) {
request[@"Extra-Header"] = @"something else";
} execute:^(BBHTTPResponse* response) {
// handle response
} error:nil];
The request's content type and content length headers will be automatically set based on the file's properties.
NSOutputStream
:[[BBHTTPRequest getResource:@"http://foo.bar/baz"] setup:^(BBHTTPRequest* request) {
[request downloadToFile:@"/path/to/file"];
} execute:^(BBHTTPResponse* response) {
// handle response
} error:nil];
No need to delete the file if the download fails midway; BBHTTP will take care of keeping everything clean.
BBHTTPExecutor* twitterExecutor = [BBHTTPExecutor initWithId:@"twitter.com"];
BBHTTPExecutor* facebookExecutor = [BBHTTPExecutor initWithId:@"facebook.com"];
twitterExecutor.maxParallelRequests = 10;
facebookExecutor.maxParallelRequests = 2;
...
BBHTTPRequest* request = [[BBHTTPRequest alloc]
initWithURL:[NSURL URLWithString:@"http://twitter.com/resource"]
andVerb:@"GET"];
request[@"Accept-Language"] = @"en-us";
request.downloadProgressBlock = ^(NSUInteger current, NSUInteger total) { /* ... */ };
request.finishBlock = ^(BBHTTPRequest* request) { /* ... */ };
[twitterExecutor executeRequest:request];
There are other built-in ways to handle content from responses. Be sure to read up the In-depth guide to response content handling.
For a comprehensive list, be sure to visit the Roadmap wiki page.
You mean other than its sleek API or the fact that it uses libcurl underneath?
Well, unlike NSURLConnection
and, consequently, any lib that relies on it, BBHTTP...
Expect: 100-Continue
header;"But my uploads work just fine..."
NSURLConnection
ignores errors until it finishes its upload, then this is the HTTP framework for you. Also, fistbump for writing your server and client. And paying attention to the specs.On a more serious tone, the motivation for this libcurl wrapper was that during development of Droplr's API server, we noticed that whenever the API rejected an upload and immediately closed the connection — which is a perfectly legal & reasonable behavior — the Cocoa-based clients would keep reporting upload progress (even though I knew the socket was closed) and eventually fail with "Request timeout", instead of the response the server had sent down the pipes.
This meant that:
NSURLConnection
wasn't waiting for the 100-Continue
provisional response before sending along the request body;NSURLConnection
wasn't realizing that a response was already sent and the connection was dying until it finished uploading what it had to upload. stubborn bastard, eh?
I did file a bug report but after a year of waiting for a response, I decided to come up with a working alternative. Coincidentally, the same day I let this library out in the open, I got a reply from Apple — closing the bug as a duplicate of some other I don't have access to.
A couple of quick tests with command line version of curl proved that curl knew how to properly handle these edge cases so it was time to build a new HTTP framework for Cocoa.
During that process, this handy build script was produced, so even if you don't want to use this library but are still interested in getting curl running on iOS, do check it out!
libcurl
(read below)libz.dylib
Security.framework
CoreServices.framework
on OSX, MobileCoreServices.framework
on iOSAppKit.framework
on OSX, UIKit.framework
on iOSNote: You can find libcurl 7.29.1-DEV binaries and headers under
Build/iOS/Static lib/libcurl
andBuild/OSX/Static lib/libcurl
. There are two versions for iOS, compiled against 6.1 SDK.libcurl.iOS.dev.a
has support for for i386 (simulator), armv7 and armv7s (iPhone 3GS and newer) whilelibcurl.iOS.appstore.a
only has support for arm architectures — making it smaller in size and thus optimized for releases. The OSX version was compiled against 10.8 SDK with support for x86_64 (64 bit Intel). If you'd like to build your own custom version, try this. All binaries are compiled with debug symbols so even though they appear large, they'll end up with 400~600KB.
For guides on how to setup and start working with this lib, check out the wiki pages.
The project also includes comprehensive class-level documentation. If you happen to have appledoc installed, just run the generate
script on the Docs
folder and it'll create html documentation for you under Docs/html
.
BBHTTP is licensed under the Apache Software License version 2.0
I'm on twitter as @biasedbit. I also write every now and then.