Ben Copsey

Requests catch exceptions and generate an error

... ... @@ -32,7 +32,8 @@ typedef enum _ASINetworkErrorType {
ASIInternalErrorWhileBuildingRequestType = 6,
ASIInternalErrorWhileApplyingCredentialsType = 7,
ASIFileManagementError = 8,
ASITooMuchRedirectionErrorType = 9
ASITooMuchRedirectionErrorType = 9,
ASIUnhandledExceptionError = 10
} ASINetworkErrorType;
... ...
... ... @@ -436,54 +436,64 @@ static BOOL isiPhoneOS2;
// Create the request
- (void)main
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self setComplete:NO];
if (![self url]) {
[self failWithError:ASIUnableToCreateRequestError];
[pool release];
return;
}
// Must call before we create the request so that the request method can be set if needs be
if (![self mainRequest]) {
[self buildPostBody];
}
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// If we're redirecting, we'll already have a CFHTTPMessageRef
if (request) {
CFRelease(request);
}
@try {
[self setComplete:NO];
if (![self url]) {
[self failWithError:ASIUnableToCreateRequestError];
[pool release];
return;
}
// Must call before we create the request so that the request method can be set if needs be
if (![self mainRequest]) {
[self buildPostBody];
}
// If we're redirecting, we'll already have a CFHTTPMessageRef
if (request) {
CFRelease(request);
}
// Create a new HTTP request.
request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)[self requestMethod], (CFURLRef)[self url], [self useHTTPVersionOne] ? kCFHTTPVersion1_0 : kCFHTTPVersion1_1);
if (!request) {
[self failWithError:ASIUnableToCreateRequestError];
[pool release];
return;
}
// Create a new HTTP request.
request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)[self requestMethod], (CFURLRef)[self url], [self useHTTPVersionOne] ? kCFHTTPVersion1_0 : kCFHTTPVersion1_1);
if (!request) {
[self failWithError:ASIUnableToCreateRequestError];
[pool release];
return;
}
//If this is a HEAD request generated by an ASINetworkQueue, we need to let the main request generate its headers first so we can use them
if ([self mainRequest]) {
[[self mainRequest] buildRequestHeaders];
}
// Even if this is a HEAD request with a mainRequest, we still need to call to give subclasses a chance to add their own to HEAD requests (ASIS3Request does this)
[self buildRequestHeaders];
[self applyAuthorizationHeader];
NSString *header;
for (header in [self requestHeaders]) {
CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[[self requestHeaders] objectForKey:header]);
}
[self loadRequest];
} @catch (NSException *exception) {
NSError *underlyingError = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASIUnhandledExceptionError userInfo:[exception userInfo]];
[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIUnhandledExceptionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[exception name],NSLocalizedDescriptionKey,[exception reason],NSLocalizedFailureReasonErrorKey,underlyingError,NSUnderlyingErrorKey,nil]]];
}
//If this is a HEAD request generated by an ASINetworkQueue, we need to let the main request generate its headers first so we can use them
if ([self mainRequest]) {
[[self mainRequest] buildRequestHeaders];
}
// Even if this is a HEAD request with a mainRequest, we still need to call to give subclasses a chance to add their own to HEAD requests (ASIS3Request does this)
[self buildRequestHeaders];
[self applyAuthorizationHeader];
NSString *header;
for (header in [self requestHeaders]) {
CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[[self requestHeaders] objectForKey:header]);
}
[self loadRequest];
[pool release];
}
- (void)applyAuthorizationHeader
... ...
... ... @@ -18,6 +18,7 @@
- (void)testBasicDownload;
- (void)testConditionalGET;
- (void)testException;
- (void)testTimeOut;
- (void)testRequestMethod;
- (void)testHTTPVersion;
... ... @@ -51,6 +52,7 @@
//- (void)testRedirectStressTest;
//- (void)performRedirectRequest;
@property (retain,nonatomic) ASIHTTPRequest *cancelRequest;
@property (retain, nonatomic) NSDate *cancelStartDate;
@end
... ...
... ... @@ -17,6 +17,12 @@
@interface ASIHTTPRequestSubclass : ASIHTTPRequest {}
@end
@implementation ASIHTTPRequestSubclass;
// For testing exceptions are caught
- (void)loadRequest
{
[[NSException exceptionWithName:@"Test Exception" reason:@"Test Reason" userInfo:nil] raise];
}
@end
@implementation ASIHTTPRequestTests
... ... @@ -85,6 +91,18 @@
}
- (void)testException
{
ASIHTTPRequestSubclass *request = [ASIHTTPRequestSubclass requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request start];
NSError *error = [request error];
GHAssertNotNil(error,@"Failed to generate an error for an exception");
BOOL success = [[[error userInfo] objectForKey:NSLocalizedDescriptionKey] isEqualToString:@"Test Exception"];
GHAssertTrue(success, @"Generated wrong error for exception");
}
- (void)testCharacterEncoding
{
... ... @@ -1100,6 +1118,7 @@
}
// This is a stress test that looks for thread-safety problems with cancelling requests
// It will run for 30 seconds, creating a request, then cancelling it and creating another as soon as it gets some indication of progress
// Uncomment to run on your local webserver. Do not use on a remote server, this test will create 1000s of requests!
... ... @@ -1177,6 +1196,7 @@
@synthesize cancelRequest;
@synthesize cancelStartDate;
@end
\ No newline at end of file
... ...
... ... @@ -927,7 +927,6 @@ IMPORTANT
NSString *expectedResponse = [[NSString stringWithFormat:@"You are %@ from %@/%@",@"king",@"Castle.Kingdom",hostName] lowercaseString];
BOOL success = [[[request responseString] lowercaseString] isEqualToString:expectedResponse];
GHAssertTrue(success,@"Failed to send credentials correctly? (Expected: '%@', got '%@')",expectedResponse,[[request responseString] lowercaseString]);
}
@synthesize immediateCancelQueue;
... ...