-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a new request factory class. Refactory JSON processing blocks acc…
…ordingly.
- Loading branch information
1 parent
ec5084a
commit 0d322f9
Showing
8 changed files
with
245 additions
and
15 deletions.
There are no files selected for viewing
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// | ||
// AEURLRequestFactory.h | ||
// AEURLExample | ||
// | ||
// Created by Adam Ernst on 10/13/11. | ||
// Copyright (c) 2011 cosmicsoft. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
typedef id (^AEURLConnectionParameterProcessingBlock)(NSDictionary *parameters, NSMutableURLRequest *targetRequest); | ||
|
||
@interface AEURLRequestFactory : NSObject { | ||
NSMutableDictionary *_defaultHeaderValues; | ||
} | ||
|
||
// A singleton request factory. If you set any default header values on this | ||
// factory, they persist to future uses. | ||
+ (AEURLRequestFactory *)defaultFactory; | ||
|
||
// This method puts parameters in the query string if method is GET; otherwise, | ||
// it puts them in the HTTP body as x-www-form-urlencoded (just like a browser- | ||
// submitted POST form). | ||
// Need to modify the returned request further? Just use -mutableCopy. | ||
- (NSURLRequest *)requestWithURL:(NSURL *)url | ||
method:(NSString *)method | ||
parameters:(NSDictionary *)parameters; | ||
|
||
// You can pass any block to put the parameters into the generated request: e.g. | ||
// JSON, or you could write your own for XML or other encodings. | ||
- (NSURLRequest *)requestWithURL:(NSURL *)url | ||
method:(NSString *)method | ||
parameters:(NSDictionary *)parameters | ||
parameterProcessingBlock:(AEURLConnectionParameterProcessingBlock)parameterProcessingBlock; | ||
|
||
- (NSString *)defaultValueForHeader:(NSString *)header; | ||
- (void)setDefaultValue:(NSString *)value forHeader:(NSString *)header; | ||
|
||
// Use this utility functions with setDefaultValue:forHeader:, passing | ||
// "Authorization" for the header. | ||
+ (NSString *)authorizationHeaderForUsername:(NSString *)username password:(NSString *)password; | ||
|
||
// A parameter processing block that puts the parameters into the query string | ||
// (usually for GET requests). | ||
+ (AEURLConnectionParameterProcessingBlock)queryStringProcessingBlock; | ||
|
||
// A parameter processing block that puts the parameters into the HTTP body in | ||
// x-www-form-urlencoded format, like a browser's POST form encoding. | ||
+ (AEURLConnectionParameterProcessingBlock)formURLEncodedProcessingBlock; | ||
|
||
// See AEJSONProcessingBlock for a parameter processing block that creates JSON. | ||
|
||
@end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// | ||
// AEURLRequestFactory.m | ||
// AEURLExample | ||
// | ||
// Created by Adam Ernst on 10/13/11. | ||
// Copyright (c) 2011 cosmicsoft. All rights reserved. | ||
// | ||
|
||
#import "AEURLRequestFactory.h" | ||
|
||
// Forward declarations: | ||
static NSString * AEURLEncodedStringFromString(NSString *string); | ||
static NSString * AEQueryStringFromParameters(NSDictionary *parameters); | ||
static NSString * AEBase64EncodedStringFromString(NSString *string); | ||
|
||
@implementation AEURLRequestFactory | ||
|
||
+ (AEURLRequestFactory *)defaultFactory { | ||
static AEURLRequestFactory *defaultFactory; | ||
static dispatch_once_t onceToken; | ||
dispatch_once(&onceToken, ^{ | ||
defaultFactory = [[AEURLRequestFactory alloc] init]; | ||
}); | ||
return defaultFactory; | ||
} | ||
|
||
- (id)init { | ||
self = [super init]; | ||
if (self) { | ||
_defaultHeaderValues = [[NSMutableDictionary alloc] init]; | ||
} | ||
return self; | ||
} | ||
|
||
- (void)dealloc { | ||
[_defaultHeaderValues release]; | ||
[super dealloc]; | ||
} | ||
|
||
- (NSURLRequest *)requestWithURL:(NSURL *)url | ||
method:(NSString *)method | ||
parameters:(NSDictionary *)parameters { | ||
AEURLConnectionParameterProcessingBlock processingBlock = nil; | ||
if ([method isEqualToString:@"GET"]) { | ||
processingBlock = [AEURLRequestFactory queryStringProcessingBlock]; | ||
} else { | ||
processingBlock = [AEURLRequestFactory formURLEncodedProcessingBlock]; | ||
} | ||
return [self requestWithURL:url method:method parameters:parameters parameterProcessingBlock:processingBlock]; | ||
} | ||
|
||
- (NSURLRequest *)requestWithURL:(NSURL *)url | ||
method:(NSString *)method | ||
parameters:(NSDictionary *)parameters | ||
parameterProcessingBlock:(AEURLConnectionParameterProcessingBlock)parameterProcessingBlock { | ||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; | ||
[request setHTTPMethod:method]; | ||
[request setAllHTTPHeaderFields:_defaultHeaderValues]; | ||
parameterProcessingBlock(parameters, request); | ||
return request; | ||
} | ||
|
||
#pragma mark - Default Header Values | ||
|
||
- (NSString *)defaultValueForHeader:(NSString *)header { | ||
return [_defaultHeaderValues objectForKey:header]; | ||
} | ||
|
||
- (void)setDefaultValue:(NSString *)value forHeader:(NSString *)header { | ||
[_defaultHeaderValues setObject:value forKey:header]; | ||
} | ||
|
||
#pragma mark - Authorization Header Generation | ||
|
||
+ (NSString *)authorizationHeaderForUsername:(NSString *)username password:(NSString *)password { | ||
return [NSString stringWithFormat:@"Basic %@", AEBase64EncodedStringFromString([NSString stringWithFormat:@"%@:%@", username, password])]; | ||
} | ||
|
||
#pragma mark - Parameter Encoding Blocks | ||
|
||
+ (AEURLConnectionParameterProcessingBlock)queryStringProcessingBlock { | ||
static AEURLConnectionParameterProcessingBlock queryStringProcessingBlock; | ||
static dispatch_once_t onceToken; | ||
dispatch_once(&onceToken, ^{ | ||
queryStringProcessingBlock = [^(NSDictionary *parameters, NSMutableURLRequest *targetRequest){ | ||
NSString *oldURL = [[targetRequest URL] absoluteString]; | ||
NSURL *newURL = [NSURL URLWithString:[oldURL stringByAppendingFormat:[oldURL rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", AEQueryStringFromParameters(parameters)]]; | ||
[targetRequest setURL:newURL]; | ||
} copy]; | ||
}); | ||
return queryStringProcessingBlock; | ||
} | ||
|
||
+ (AEURLConnectionParameterProcessingBlock)formURLEncodedProcessingBlock { | ||
static AEURLConnectionParameterProcessingBlock formURLEncodedProcessingBlock; | ||
static dispatch_once_t onceToken; | ||
dispatch_once(&onceToken, ^{ | ||
formURLEncodedProcessingBlock = [^(NSDictionary *parameters, NSMutableURLRequest *targetRequest){ | ||
[targetRequest setValue:@"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; | ||
[targetRequest setHTTPBody:[AEQueryStringFromParameters(parameters) dataUsingEncoding:NSUTF8StringEncoding]]; | ||
} copy]; | ||
}); | ||
return formURLEncodedProcessingBlock; | ||
} | ||
|
||
#pragma mark - URLEncoding | ||
|
||
// These functions are based on AFNetworking's equivalents (substituting AE for | ||
// AF in the function prefix to prevent linker conflicts). Thanks AFNetworking! | ||
// (Used with permission.) | ||
|
||
static NSString * AEURLEncodedStringFromString(NSString *string) { | ||
static NSString * const kAFLegalCharactersToBeEscaped = @"?!@#$^&%*+,:;='\"`<>()[]{}/\\|~ "; | ||
|
||
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) autorelease]; | ||
} | ||
|
||
static NSString * AEQueryStringFromParameters(NSDictionary *parameters) { | ||
NSMutableArray *mutableParameterComponents = [NSMutableArray array]; | ||
for (id key in [parameters allKeys]) { | ||
NSString *component = [NSString stringWithFormat:@"%@=%@", AEURLEncodedStringFromString([key description]), AEURLEncodedStringFromString([[parameters valueForKey:key] description])]; | ||
[mutableParameterComponents addObject:component]; | ||
} | ||
|
||
return [mutableParameterComponents componentsJoinedByString:@"&"]; | ||
} | ||
|
||
static NSString * AEBase64EncodedStringFromString(NSString *string) { | ||
NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string length]]; | ||
NSUInteger length = [data length]; | ||
NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; | ||
|
||
uint8_t *input = (uint8_t *)[data bytes]; | ||
uint8_t *output = (uint8_t *)[mutableData mutableBytes]; | ||
|
||
for (NSUInteger i = 0; i < length; i += 3) { | ||
NSUInteger value = 0; | ||
for (NSUInteger j = i; j < (i + 3); j++) { | ||
value <<= 8; | ||
if (j < length) { | ||
value |= (0xFF & input[j]); | ||
} | ||
} | ||
|
||
static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
|
||
NSUInteger idx = (i / 3) * 4; | ||
output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F]; | ||
output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F]; | ||
output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '='; | ||
output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '='; | ||
} | ||
|
||
return [[[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding] autorelease]; | ||
} | ||
|
||
@end |
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
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