Ben Copsey

Allow a custom selector for handling response data in the delegate

Add test for same
... ... @@ -255,6 +255,10 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
// Called on the delegate (if implemented) when the request fails. Default is requestFailed:
SEL didFailSelector;
// Called on the delegate (if implemented) when the request receives data. Default is request:didReceiveData:
// If you set this and implement the method in your delegate, you must handle the data yourself - ASIHTTPRequest will not populate responseData or write the data to downloadDestinationPath
SEL didReceiveDataSelector;
// Used for recording when something last happened during the request, we will compare this value with the current date to time out requests when appropriate
NSDate *lastActivityTime;
... ... @@ -699,6 +703,7 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
@property (assign) SEL didReceiveResponseHeadersSelector;
@property (assign) SEL didFinishSelector;
@property (assign) SEL didFailSelector;
@property (assign) SEL didReceiveDataSelector;
@property (retain,readonly) NSString *authenticationRealm;
@property (retain,readonly) NSString *proxyAuthenticationRealm;
@property (retain) NSError *error;
... ...
... ... @@ -23,7 +23,7 @@
// Automatically set on build
NSString *ASIHTTPRequestVersion = @"v1.6.1-14 2010-04-14";
NSString *ASIHTTPRequestVersion = @"v1.6.1-15 2010-04-14";
NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
... ... @@ -244,6 +244,7 @@ static BOOL isiPhoneOS2;
[self setDidReceiveResponseHeadersSelector:@selector(requestReceivedResponseHeaders:)];
[self setDidFinishSelector:@selector(requestFinished:)];
[self setDidFailSelector:@selector(requestFailed:)];
[self setDidReceiveDataSelector:@selector(request:didReceiveData:)];
[self setURL:newURL];
[self setCancelledLock:[[[NSRecursiveLock alloc] init] autorelease]];
return self;
... ... @@ -2454,14 +2455,15 @@ static BOOL isiPhoneOS2;
}
// Does the delegate want to handle the data manually?
SEL receivedDataSelector = @selector(request:didReceiveData:);
if ([[self delegate] respondsToSelector:receivedDataSelector]) {
NSMethodSignature *signature = [[[self delegate] class] instanceMethodSignatureForSelector:receivedDataSelector];
if ([[self delegate] respondsToSelector:[self didReceiveDataSelector]]) {
NSMethodSignature *signature = [[[self delegate] class] instanceMethodSignatureForSelector:[self didReceiveDataSelector]];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:[self delegate]];
[invocation setSelector:receivedDataSelector];
[invocation setArgument:self atIndex:2];
[invocation setArgument:[NSData dataWithBytes:buffer length:bytesRead] atIndex:3];
[invocation setSelector:[self didReceiveDataSelector]];
[invocation setArgument:&self atIndex:2];
NSData *data = [NSData dataWithBytes:buffer length:bytesRead];
[invocation setArgument:&data atIndex:3];
[invocation retainArguments];
[invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:[self delegate] waitUntilDone:[NSThread isMainThread]];
// Are we downloading to a file?
... ... @@ -3669,6 +3671,7 @@ static BOOL isiPhoneOS2;
@synthesize didReceiveResponseHeadersSelector;
@synthesize didFinishSelector;
@synthesize didFailSelector;
@synthesize didReceiveDataSelector;
@synthesize authenticationRealm;
@synthesize proxyAuthenticationRealm;
@synthesize error;
... ...
... ... @@ -21,6 +21,7 @@
// When a delegate implements this method, it is expected to process all incoming data itself
// This means that responseData / responseString / downloadDestinationPath etc are ignored
// You can have the request call a different method by setting didReceiveDataSelector
- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;
// If a delegate implements one of these, it will be asked to supply credentials when none are available
... ...
... ... @@ -15,6 +15,8 @@
BOOL started;
BOOL finished;
BOOL failed;
BOOL receivedResponseHeaders;
NSMutableData *responseData;
}
- (void)testBasicDownload;
... ... @@ -62,4 +64,6 @@
- (void)testAutomaticRetry;
- (void)testCloseConnection;
- (void)testPersistentConnectionTimeout;
@property (retain, nonatomic) NSMutableData *responseData;
@end
... ...
... ... @@ -122,6 +122,7 @@
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
GHAssertTrue(started,@"Failed to call the delegate method when the request started");
GHAssertTrue(receivedResponseHeaders,@"Failed to call the delegate method when the request started");
GHAssertTrue(finished,@"Failed to call the delegate method when the request finished");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"]];
... ... @@ -134,11 +135,13 @@
started = NO;
finished = NO;
failed = NO;
receivedResponseHeaders = NO;
// Test custom delegate methods
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setDelegate:self];
[request setDidStartSelector:@selector(delegateTestStarted:)];
[request setDidReceiveResponseHeadersSelector:@selector(delegateTestResponseHeaders:)];
[request setDidFinishSelector:@selector(delegateTestFinished:)];
[request startSynchronous];
... ... @@ -161,6 +164,13 @@
started = YES;
}
- (void)requestReceivedResponseHeaders:(ASIHTTPRequest *)request
{
GHAssertNotNil([request responseHeaders],@"Called requestReceivedResponseHeaders: when we have no headers");
receivedResponseHeaders = YES;
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
finished = YES;
... ... @@ -176,6 +186,12 @@
started = YES;
}
- (void)delegateTestResponseHeaders:(ASIHTTPRequest *)request
{
GHAssertNotNil([request responseHeaders],@"Called delegateTestResponseHeaders: when we have no headers");
receivedResponseHeaders = YES;
}
- (void)delegateTestFinished:(ASIHTTPRequest *)request
{
finished = YES;
... ... @@ -1539,4 +1555,29 @@
GHAssertTrue(success,@"Failed to return the default mime type when a file has no extension");
}
- (void)testDelegateResponseDataHandling
{
[self setResponseData:[NSMutableData dataWithLength:0]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28young_readers_edition%29.txt"]];
[request setDelegate:self];
[request setDidReceiveDataSelector:@selector(testRequest:didReceiveData:)];
[request setDidFinishSelector:@selector(testRequestFinished:)];
[request startAsynchronous];
}
- (void)testRequestFinished:(ASIHTTPRequest *)request
{
ASIHTTPRequest *request2 = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28young_readers_edition%29.txt"]];
[request2 startSynchronous];
NSString *firstResponse = [[[NSString alloc] initWithBytes:[[self responseData] bytes] length:[[self responseData] length] encoding:[request responseEncoding]] autorelease];
BOOL success = [[request2 responseString] isEqualToString:firstResponse];
GHAssertTrue(success,@"Failed to correctly download and store the response using a delegate");
}
- (void)testRequest:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
{
[[self responseData] appendData:data];
}
@synthesize responseData;
@end
\ No newline at end of file
... ...