Merge branch 'experimental-http-basic-auth-helper'

This commit is contained in:
Mattt Thompson 2011-08-31 09:50:03 -05:00
commit c0271e6156
6 changed files with 94 additions and 28 deletions

View file

@ -56,6 +56,7 @@ extern NSString * const AFHTTPOperationDidFinishNotification;
outputStream:(NSOutputStream *)outputStream outputStream:(NSOutputStream *)outputStream
completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion; completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion;
- (void)setProgressBlock:(void (^)(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite))block; - (void)setUploadProgressBlock:(void (^)(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite))block;
- (void)setDownloadProgressBlock:(void (^)(NSUInteger totalBytesRead, NSUInteger totalBytesExpectedToRead))block;
@end @end

View file

@ -33,7 +33,7 @@ typedef enum {
NSString * const AFHTTPOperationDidStartNotification = @"com.alamofire.http-operation.start"; NSString * const AFHTTPOperationDidStartNotification = @"com.alamofire.http-operation.start";
NSString * const AFHTTPOperationDidFinishNotification = @"com.alamofire.http-operation.finish"; NSString * const AFHTTPOperationDidFinishNotification = @"com.alamofire.http-operation.finish";
typedef void (^AFHTTPRequestOperationProgressBlock)(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite); typedef void (^AFHTTPRequestOperationProgressBlock)(NSUInteger totalBytes, NSUInteger totalBytesExpected);
typedef void (^AFHTTPRequestOperationCompletionBlock)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error); typedef void (^AFHTTPRequestOperationCompletionBlock)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error);
static inline NSString * AFKeyPathFromOperationState(AFHTTPOperationState state) { static inline NSString * AFKeyPathFromOperationState(AFHTTPOperationState state) {
@ -79,13 +79,14 @@ static inline BOOL AFHTTPOperationStateTransitionIsValid(AFHTTPOperationState fr
@interface AFHTTPRequestOperation () @interface AFHTTPRequestOperation ()
@property (nonatomic, assign) AFHTTPOperationState state; @property (nonatomic, assign) AFHTTPOperationState state;
@property (nonatomic, assign) BOOL isCancelled; @property (nonatomic, assign) BOOL isCancelled;
@property (readwrite, nonatomic, assign) NSUInteger totalBytesRead;
@property (readwrite, nonatomic, retain) NSMutableData *dataAccumulator; @property (readwrite, nonatomic, retain) NSMutableData *dataAccumulator;
@property (readwrite, nonatomic, retain) NSOutputStream *outputStream; @property (readwrite, nonatomic, retain) NSOutputStream *outputStream;
@property (readwrite, nonatomic, copy) AFHTTPRequestOperationProgressBlock progress; @property (readwrite, nonatomic, copy) AFHTTPRequestOperationProgressBlock uploadProgress;
@property (readwrite, nonatomic, copy) AFHTTPRequestOperationProgressBlock downloadProgress;
@property (readwrite, nonatomic, copy) AFHTTPRequestOperationCompletionBlock completion; @property (readwrite, nonatomic, copy) AFHTTPRequestOperationCompletionBlock completion;
- (id)initWithRequest:(NSURLRequest *)urlRequest; - (id)initWithRequest:(NSURLRequest *)urlRequest;
- (void)cleanup;
@end @end
@implementation AFHTTPRequestOperation @implementation AFHTTPRequestOperation
@ -97,11 +98,32 @@ static inline BOOL AFHTTPOperationStateTransitionIsValid(AFHTTPOperationState fr
@synthesize response = _response; @synthesize response = _response;
@synthesize error = _error; @synthesize error = _error;
@synthesize responseBody = _responseBody; @synthesize responseBody = _responseBody;
@synthesize totalBytesRead = _totalBytesRead;
@synthesize dataAccumulator = _dataAccumulator; @synthesize dataAccumulator = _dataAccumulator;
@synthesize outputStream = _outputStream; @synthesize outputStream = _outputStream;
@synthesize progress = _progress; @synthesize uploadProgress = _uploadProgress;
@synthesize downloadProgress = _downloadProgress;
@synthesize completion = _completion; @synthesize completion = _completion;
static NSThread *_networkRequestThread = nil;
+ (NSThread *)networkRequestThread {
if (!_networkRequestThread) {
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
[_networkRequestThread start];
}
return _networkRequestThread;
}
+ (void)networkRequestThreadEntryPoint:(id)object {
do {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[[NSRunLoop currentRunLoop] run];
[pool drain];
} while (YES);
}
+ (id)operationWithRequest:(NSURLRequest *)urlRequest + (id)operationWithRequest:(NSURLRequest *)urlRequest
completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion
{ {
@ -157,25 +179,21 @@ static inline BOOL AFHTTPOperationStateTransitionIsValid(AFHTTPOperationState fr
[_connection release]; _connection = nil; [_connection release]; _connection = nil;
[_progress release]; [_uploadProgress release];
[_downloadProgress release];
[_completion release]; [_completion release];
[_progress release];
[super dealloc]; [super dealloc];
} }
- (void)cleanup { - (void)setUploadProgressBlock:(void (^)(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite))block {
[self.outputStream close]; self.uploadProgress = block;
for (NSString *runLoopMode in self.runLoopModes) {
[self.connection unscheduleFromRunLoop:[NSRunLoop currentRunLoop] forMode:runLoopMode];
[self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:runLoopMode];
}
CFRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
} }
- (void)setProgressBlock:(void (^)(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite))block { - (void)setDownloadProgressBlock:(void (^)(NSUInteger totalBytesRead, NSUInteger totalBytesExpectedToRead))block {
self.progress = block; self.downloadProgress = block;
} }
- (void)setState:(AFHTTPOperationState)state { - (void)setState:(AFHTTPOperationState)state {
if (!AFHTTPOperationStateTransitionIsValid(self.state, state)) { if (!AFHTTPOperationStateTransitionIsValid(self.state, state)) {
return; return;
@ -198,7 +216,6 @@ static inline BOOL AFHTTPOperationStateTransitionIsValid(AFHTTPOperationState fr
case AFHTTPOperationFinishedState: case AFHTTPOperationFinishedState:
[[AFNetworkActivityIndicatorManager sharedManager] stopAnimating]; [[AFNetworkActivityIndicatorManager sharedManager] stopAnimating];
[[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidFinishNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidFinishNotification object:self];
[self cleanup];
break; break;
default: default:
break; break;
@ -233,7 +250,11 @@ static inline BOOL AFHTTPOperationStateTransitionIsValid(AFHTTPOperationState fr
} }
self.state = AFHTTPOperationExecutingState; self.state = AFHTTPOperationExecutingState;
[self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:YES modes:[self.runLoopModes allObjects]];
}
- (void)operationDidStart {
self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease]; self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
@ -243,16 +264,13 @@ static inline BOOL AFHTTPOperationStateTransitionIsValid(AFHTTPOperationState fr
} }
[self.connection start]; [self.connection start];
[runLoop run];
} }
- (void)cancel { - (void)cancel {
self.isCancelled = YES; self.isCancelled = YES;
[self.connection cancel]; [self.connection cancel];
[self cleanup];
} }
#pragma mark - AFHTTPRequestOperation #pragma mark - AFHTTPRequestOperation
@ -285,6 +303,8 @@ didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection - (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data didReceiveData:(NSData *)data
{ {
self.totalBytesRead += [data length];
if (self.outputStream) { if (self.outputStream) {
if ([self.outputStream hasSpaceAvailable]) { if ([self.outputStream hasSpaceAvailable]) {
const uint8_t *dataBuffer = [data bytes]; const uint8_t *dataBuffer = [data bytes];
@ -293,6 +313,10 @@ didReceiveResponse:(NSURLResponse *)response
} else { } else {
[self.dataAccumulator appendData:data]; [self.dataAccumulator appendData:data];
} }
if (self.downloadProgress) {
self.downloadProgress(self.totalBytesRead, self.response.expectedContentLength);
}
} }
- (void)connectionDidFinishLoading:(NSURLConnection *)connection { - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
@ -305,7 +329,7 @@ didReceiveResponse:(NSURLResponse *)response
[_dataAccumulator release]; _dataAccumulator = nil; [_dataAccumulator release]; _dataAccumulator = nil;
} }
[self performSelectorOnMainThread:@selector(finish) withObject:nil waitUntilDone:NO]; [self finish];
} }
- (void)connection:(NSURLConnection *)connection - (void)connection:(NSURLConnection *)connection
@ -315,7 +339,7 @@ didReceiveResponse:(NSURLResponse *)response
self.error = error; self.error = error;
[self performSelectorOnMainThread:@selector(finish) withObject:nil waitUntilDone:NO]; [self finish];
} }
- (void)connection:(NSURLConnection *)connection - (void)connection:(NSURLConnection *)connection
@ -323,12 +347,14 @@ didReceiveResponse:(NSURLResponse *)response
totalBytesWritten:(NSInteger)totalBytesWritten totalBytesWritten:(NSInteger)totalBytesWritten
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{ {
if (self.progress) { if (self.uploadProgress) {
self.progress(totalBytesWritten, totalBytesExpectedToWrite); self.uploadProgress(totalBytesWritten, totalBytesExpectedToWrite);
} }
} }
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { - (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
if ([self isCancelled]) { if ([self isCancelled]) {
return nil; return nil;
} }

View file

@ -38,6 +38,7 @@
- (NSString *)defaultValueForHeader:(NSString *)header; - (NSString *)defaultValueForHeader:(NSString *)header;
- (void)setDefaultHeader:(NSString *)header value:(NSString *)value; - (void)setDefaultHeader:(NSString *)header value:(NSString *)value;
- (void)setAuthorizationHeaderWithUsername:(NSString *)username password:(NSString *)password;
- (void)setAuthorizationHeaderWithToken:(NSString *)token; - (void)setAuthorizationHeaderWithToken:(NSString *)token;
- (void)clearAuthorizationHeader; - (void)clearAuthorizationHeader;

View file

@ -23,6 +23,8 @@
#import "AFRestClient.h" #import "AFRestClient.h"
#import "AFJSONRequestOperation.h" #import "AFJSONRequestOperation.h"
#import "NSData+AFNetworking.h"
static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding; static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding;
@interface AFRestClient () @interface AFRestClient ()
@ -86,6 +88,12 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding
[self.defaultHeaders setObject:value forKey:header]; [self.defaultHeaders setObject:value forKey:header];
} }
- (void)setAuthorizationHeaderWithUsername:(NSString *)username password:(NSString *)password {
NSString *authHeader = [NSString stringWithFormat:@"%@:%@", username, password];
NSString *encodedAuthHeader = [[NSData dataWithBytes:[authHeader UTF8String] length:[authHeader length]] base64EncodedString];
[self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Basic %@", encodedAuthHeader]];
}
- (void)setAuthorizationHeaderWithToken:(NSString *)token { - (void)setAuthorizationHeaderWithToken:(NSString *)token {
[self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Token token=\"%@\"", token]]; [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Token token=\"%@\"", token]];
} }

View file

@ -26,6 +26,7 @@ extern NSString * const kAFZlibErrorDomain;
@interface NSData (AFNetworking) @interface NSData (AFNetworking)
- (NSString *)base64EncodedString;
- (NSData *)dataByGZipCompressingWithError:(NSError **)error; - (NSData *)dataByGZipCompressingWithError:(NSError **)error;
- (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error; - (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error;

View file

@ -25,6 +25,8 @@
NSString * const kAFZlibErrorDomain = @"com.alamofire.zlib.error"; NSString * const kAFZlibErrorDomain = @"com.alamofire.zlib.error";
static char Base64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static inline NSUInteger NSDataEstimatedCompressedLength(NSData *data) { static inline NSUInteger NSDataEstimatedCompressedLength(NSData *data) {
return [data length] / 2; return [data length] / 2;
} }
@ -88,6 +90,33 @@ typedef enum {
@implementation NSData (AFNetworking) @implementation NSData (AFNetworking)
- (NSString *)base64EncodedString {
NSUInteger length = [self length];
NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *input = (uint8_t *)[self 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]);
}
}
NSInteger idx = (i / 3) * 4;
output[idx + 0] = Base64EncodingTable[(value >> 18) & 0x3F];
output[idx + 1] = Base64EncodingTable[(value >> 12) & 0x3F];
output[idx + 2] = (i + 1) < length ? Base64EncodingTable[(value >> 6) & 0x3F] : '=';
output[idx + 3] = (i + 2) < length ? Base64EncodingTable[(value >> 0) & 0x3F] : '=';
}
return [[[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding] autorelease];
}
- (NSData *)dataByGZipCompressingWithError:(NSError **)error { - (NSData *)dataByGZipCompressingWithError:(NSError **)error {
return [NSData dataByTransformingData:self usingGZipOperation:GzipDeflate error:error]; return [NSData dataByTransformingData:self usingGZipOperation:GzipDeflate error:error];
} }