Created
November 19, 2011 00:27
-
-
Save indragiek/1378191 to your computer and use it in GitHub Desktop.
Retrieving album artwork from Amazon's Product Services API in Cocoa (using AFNetworking)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static NSString* const kAWSAccessKey = @"__ACCESS__KEY__"; // From AWS Developer portal | |
static NSString* const kAWSSecretKey = @"__SECRET__KEY__"; // From AWS Developer portal | |
static NSString* const kAWSAssociateTag = @"examp-99"; // Can be a bogus tag in the format xxxxx-XX (x being a letter and X being a number) | |
/* NSString category for HMAC and URL string encoding */ | |
@interface NSString (AWSAdditions) | |
- (NSString*)URLEncodedStringForCharacters:(NSString*)characters; | |
+ (NSData*)HMACSHA256EncodedDataWithKey:(NSString*)key data:(NSString*)data; | |
@end | |
#import <CommonCrypto/CommonHMAC.h> | |
@implementation NSString (AWSAdditions) | |
- (NSString*)URLEncodedStringForCharacters:(NSString*)characters | |
{ | |
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)self, NULL, (__bridge CFStringRef)characters, kCFStringEncodingUTF8); | |
} | |
+ (NSData*)HMACSHA256EncodedDataWithKey:(NSString*)key data:(NSString*)data | |
{ | |
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; | |
const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding]; | |
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH]; | |
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC); | |
return [[NSData alloc] initWithBytes:cHMAC length:CC_SHA256_DIGEST_LENGTH]; | |
} | |
@end | |
#import "AFXMLRequestOperation.h" | |
/* Method that makes a request to Amazon's API and grabs the URL for the artwork | |
Once the URL has been retrieved, you can use whatever method you want to download the image at the URL (e.g. AFImageRequestOperation) | |
*/ | |
- (void)artworkURLForAlbumWithTitle:(NSString*)title artist:(NSString*)artist completionHandler:(void (^)(NSURL *url, NSError *error))handler | |
{ | |
// Amazon Product Services API requires a timestamp in a specific format | |
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; | |
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; | |
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; | |
NSString *date = [dateFormatter stringFromDate:[NSDate date]]; | |
// Order the paramters in byte order | |
NSString *parameters = [NSString stringWithFormat:@"AWSAccessKeyId=%@&Artist=%@&AssociateTag=%@&Operation=ItemSearch&ResponseGroup=Images&SearchIndex=Music&Service=AWSECommerceService&Timestamp=%@&Title=%@", kAWSAccessKey, artist, kAWSAssociateTag, date, title]; | |
NSString *escaped = [parameters URLEncodedStringForCharacters:@"!*'();:@+$,/?%#[]"]; // Percent escape parameters | |
NSString *sign = [NSString stringWithFormat:@"GET\nwebservices.amazon.com\n/onca/xml\n%@", escaped]; // The string that will be encoded as the signature | |
NSData *hmac = [NSString HMACSHA256EncodedDataWithKey:kAWSSecretKey data:sign]; // HMAC encode signature with SHA256 | |
// The -base64EncodedString is from Matt Gallagher <http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html> | |
NSMutableString *encoded = [NSMutableString stringWithString:[hmac base64EncodedString]]; // Encode signature as base64 | |
NSString *signature = [encoded URLEncodedStringForCharacters:@"+="]; // Percent escape encoded signature | |
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; | |
AFXMLRequestOperation *operation = [AFXMLRequestOperation XMLDocumentRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLDocument *document) { | |
// Grab the path to the large artwork image using XPath | |
NSArray *nodes = [document nodesForXPath:@"/ItemSearchResponse/Items/Item[1]/LargeImage/URL/text()" error:nil]; | |
if ([nodes count]) { | |
NSXMLNode *node = [nodes objectAtIndex:0]; | |
NSURL *artworkURL = [NSURL URLWithString:node.stringValue]; // Grab the text from the node and create a URL | |
if (handler) { handler(artworkURL, nil); } | |
} | |
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLDocument *document) { | |
if (handler) { handler(nil, error); } | |
}]; | |
[operationQueue addOperation:operation]; // operationQueue is the NSOperationQueue you want the request to run on | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment