Add test for S3 gzipped content
Tweaks to use accessor for cancelledLock
Showing
3 changed files
with
60 additions
and
20 deletions
| @@ -72,6 +72,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -72,6 +72,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 72 | @property (assign, nonatomic) int redirectCount; | 72 | @property (assign, nonatomic) int redirectCount; |
| 73 | @property (retain, nonatomic) NSData *compressedPostBody; | 73 | @property (retain, nonatomic) NSData *compressedPostBody; |
| 74 | @property (retain, nonatomic) NSString *compressedPostBodyFilePath; | 74 | @property (retain, nonatomic) NSString *compressedPostBodyFilePath; |
| 75 | + @property (retain) NSConditionLock *authenticationLock; | ||
| 75 | @end | 76 | @end |
| 76 | 77 | ||
| 77 | @implementation ASIHTTPRequest | 78 | @implementation ASIHTTPRequest |
| @@ -428,15 +429,14 @@ static NSError *ASITooMuchRedirectionError; | @@ -428,15 +429,14 @@ static NSError *ASITooMuchRedirectionError; | ||
| 428 | 429 | ||
| 429 | - (void)startRequest | 430 | - (void)startRequest |
| 430 | { | 431 | { |
| 431 | - [cancelledLock lock]; | 432 | + [[self cancelledLock] lock]; |
| 432 | 433 | ||
| 433 | if ([self isCancelled]) { | 434 | if ([self isCancelled]) { |
| 434 | - [cancelledLock unlock]; | 435 | + [[self cancelledLock] unlock]; |
| 435 | return; | 436 | return; |
| 436 | } | 437 | } |
| 437 | 438 | ||
| 438 | - [authenticationLock release]; | 439 | + [self setAuthenticationLock:[[[NSConditionLock alloc] initWithCondition:1] autorelease]]; |
| 439 | - authenticationLock = [[NSConditionLock alloc] initWithCondition:1]; | ||
| 440 | 440 | ||
| 441 | [self setComplete:NO]; | 441 | [self setComplete:NO]; |
| 442 | [self setTotalBytesRead:0]; | 442 | [self setTotalBytesRead:0]; |
| @@ -470,7 +470,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -470,7 +470,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 470 | readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request); | 470 | readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request); |
| 471 | } | 471 | } |
| 472 | if (!readStream) { | 472 | if (!readStream) { |
| 473 | - [cancelledLock unlock]; | 473 | + [[self cancelledLock] unlock]; |
| 474 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Unable to create read stream",NSLocalizedDescriptionKey,nil]]]; | 474 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Unable to create read stream",NSLocalizedDescriptionKey,nil]]]; |
| 475 | return; | 475 | return; |
| 476 | } | 476 | } |
| @@ -502,7 +502,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -502,7 +502,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 502 | if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) { | 502 | if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) { |
| 503 | CFRelease(readStream); | 503 | CFRelease(readStream); |
| 504 | readStream = NULL; | 504 | readStream = NULL; |
| 505 | - [cancelledLock unlock]; | 505 | + [[self cancelledLock] unlock]; |
| 506 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Unable to setup read stream",NSLocalizedDescriptionKey,nil]]]; | 506 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Unable to setup read stream",NSLocalizedDescriptionKey,nil]]]; |
| 507 | return; | 507 | return; |
| 508 | } | 508 | } |
| @@ -516,11 +516,11 @@ static NSError *ASITooMuchRedirectionError; | @@ -516,11 +516,11 @@ static NSError *ASITooMuchRedirectionError; | ||
| 516 | CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), ASIHTTPRequestRunMode); | 516 | CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), ASIHTTPRequestRunMode); |
| 517 | CFRelease(readStream); | 517 | CFRelease(readStream); |
| 518 | readStream = NULL; | 518 | readStream = NULL; |
| 519 | - [cancelledLock unlock]; | 519 | + [[self cancelledLock] unlock]; |
| 520 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Unable to start HTTP connection",NSLocalizedDescriptionKey,nil]]]; | 520 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Unable to start HTTP connection",NSLocalizedDescriptionKey,nil]]]; |
| 521 | return; | 521 | return; |
| 522 | } | 522 | } |
| 523 | - [cancelledLock unlock]; | 523 | + [[self cancelledLock] unlock]; |
| 524 | 524 | ||
| 525 | 525 | ||
| 526 | if (shouldResetProgressIndicators) { | 526 | if (shouldResetProgressIndicators) { |
| @@ -606,7 +606,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -606,7 +606,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 606 | // Cancel loading and clean up | 606 | // Cancel loading and clean up |
| 607 | - (void)cancelLoad | 607 | - (void)cancelLoad |
| 608 | { | 608 | { |
| 609 | - [cancelledLock lock]; | 609 | + [[self cancelledLock] lock]; |
| 610 | if (readStream) { | 610 | if (readStream) { |
| 611 | CFReadStreamClose(readStream); | 611 | CFReadStreamClose(readStream); |
| 612 | CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL); | 612 | CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL); |
| @@ -636,7 +636,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -636,7 +636,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 636 | } | 636 | } |
| 637 | 637 | ||
| 638 | [self setResponseHeaders:nil]; | 638 | [self setResponseHeaders:nil]; |
| 639 | - [cancelledLock unlock]; | 639 | + [[self cancelledLock] unlock]; |
| 640 | } | 640 | } |
| 641 | 641 | ||
| 642 | 642 | ||
| @@ -738,9 +738,9 @@ static NSError *ASITooMuchRedirectionError; | @@ -738,9 +738,9 @@ static NSError *ASITooMuchRedirectionError; | ||
| 738 | 738 | ||
| 739 | - (void)updateUploadProgress | 739 | - (void)updateUploadProgress |
| 740 | { | 740 | { |
| 741 | - [cancelledLock lock]; | 741 | + [[self cancelledLock] lock]; |
| 742 | if ([self isCancelled]) { | 742 | if ([self isCancelled]) { |
| 743 | - [cancelledLock unlock]; | 743 | + [[self cancelledLock] unlock]; |
| 744 | return; | 744 | return; |
| 745 | } | 745 | } |
| 746 | 746 | ||
| @@ -763,7 +763,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -763,7 +763,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 763 | 763 | ||
| 764 | 764 | ||
| 765 | 765 | ||
| 766 | - [cancelledLock unlock]; | 766 | + [[self cancelledLock] unlock]; |
| 767 | 767 | ||
| 768 | if (totalBytesSent == 0) { | 768 | if (totalBytesSent == 0) { |
| 769 | return; | 769 | return; |
| @@ -1250,7 +1250,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -1250,7 +1250,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 1250 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to apply credentials to request",NSLocalizedDescriptionKey,nil]]]; | 1250 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to apply credentials to request",NSLocalizedDescriptionKey,nil]]]; |
| 1251 | } | 1251 | } |
| 1252 | 1252 | ||
| 1253 | - // Are a user name & password needed? | 1253 | + // Are a user name & password needed? |
| 1254 | } else if (CFHTTPAuthenticationRequiresUserNameAndPassword(requestAuthentication)) { | 1254 | } else if (CFHTTPAuthenticationRequiresUserNameAndPassword(requestAuthentication)) { |
| 1255 | 1255 | ||
| 1256 | NSMutableDictionary *newCredentials = [self findCredentials]; | 1256 | NSMutableDictionary *newCredentials = [self findCredentials]; |
| @@ -1341,7 +1341,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -1341,7 +1341,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 1341 | if (bytesRead < 0) { | 1341 | if (bytesRead < 0) { |
| 1342 | [self handleStreamError]; | 1342 | [self handleStreamError]; |
| 1343 | 1343 | ||
| 1344 | - // If zero bytes were read, wait for the EOF to come. | 1344 | + // If zero bytes were read, wait for the EOF to come. |
| 1345 | } else if (bytesRead) { | 1345 | } else if (bytesRead) { |
| 1346 | 1346 | ||
| 1347 | [self setTotalBytesRead:[self totalBytesRead]+bytesRead]; | 1347 | [self setTotalBytesRead:[self totalBytesRead]+bytesRead]; |
| @@ -1361,7 +1361,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -1361,7 +1361,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 1361 | } | 1361 | } |
| 1362 | [fileDownloadOutputStream write:buffer maxLength:bytesRead]; | 1362 | [fileDownloadOutputStream write:buffer maxLength:bytesRead]; |
| 1363 | 1363 | ||
| 1364 | - //Otherwise, let's add the data to our in-memory store | 1364 | + //Otherwise, let's add the data to our in-memory store |
| 1365 | } else { | 1365 | } else { |
| 1366 | [rawResponseData appendBytes:buffer length:bytesRead]; | 1366 | [rawResponseData appendBytes:buffer length:bytesRead]; |
| 1367 | } | 1367 | } |
| @@ -1571,7 +1571,6 @@ static NSError *ASITooMuchRedirectionError; | @@ -1571,7 +1571,6 @@ static NSError *ASITooMuchRedirectionError; | ||
| 1571 | [ASIHTTPRequest setSessionCookies:nil]; | 1571 | [ASIHTTPRequest setSessionCookies:nil]; |
| 1572 | } | 1572 | } |
| 1573 | 1573 | ||
| 1574 | - | ||
| 1575 | #pragma mark gzip decompression | 1574 | #pragma mark gzip decompression |
| 1576 | 1575 | ||
| 1577 | // | 1576 | // |
| @@ -1656,7 +1655,7 @@ static NSError *ASITooMuchRedirectionError; | @@ -1656,7 +1655,7 @@ static NSError *ASITooMuchRedirectionError; | ||
| 1656 | // http://www.zlib.net/zpipe.c | 1655 | // http://www.zlib.net/zpipe.c |
| 1657 | // | 1656 | // |
| 1658 | #define CHUNK 16384 | 1657 | #define CHUNK 16384 |
| 1659 | -#define SET_BINARY_MODE(file) | 1658 | + |
| 1660 | + (int)uncompressZippedDataFromSource:(FILE *)source toDestination:(FILE *)dest | 1659 | + (int)uncompressZippedDataFromSource:(FILE *)source toDestination:(FILE *)dest |
| 1661 | { | 1660 | { |
| 1662 | int ret; | 1661 | int ret; |
| @@ -1906,4 +1905,5 @@ static NSError *ASITooMuchRedirectionError; | @@ -1906,4 +1905,5 @@ static NSError *ASITooMuchRedirectionError; | ||
| 1906 | @synthesize needsRedirect; | 1905 | @synthesize needsRedirect; |
| 1907 | @synthesize redirectCount; | 1906 | @synthesize redirectCount; |
| 1908 | @synthesize shouldCompressRequestBody; | 1907 | @synthesize shouldCompressRequestBody; |
| 1908 | +@synthesize authenticationLock; | ||
| 1909 | @end | 1909 | @end |
| @@ -121,7 +121,7 @@ static NSString *bucket = @""; | @@ -121,7 +121,7 @@ static NSString *bucket = @""; | ||
| 121 | 121 | ||
| 122 | NSString *path = @"/test"; | 122 | NSString *path = @"/test"; |
| 123 | 123 | ||
| 124 | - // Create the fle | 124 | + // Create the file |
| 125 | NSString *text = @"This is my content"; | 125 | NSString *text = @"This is my content"; |
| 126 | NSString *filePath = [[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"testfile.txt"]; | 126 | NSString *filePath = [[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"testfile.txt"]; |
| 127 | [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO]; | 127 | [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO]; |
| @@ -205,6 +205,47 @@ static NSString *bucket = @""; | @@ -205,6 +205,47 @@ static NSString *bucket = @""; | ||
| 205 | GHAssertTrue(success, @"Got the wrong error message"); | 205 | GHAssertTrue(success, @"Got the wrong error message"); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | +// Will upload a file to S3, gzipping it before uploading | ||
| 209 | +// The file will be stored deflate, and automatically inflated when downloaded | ||
| 210 | +// This means the file will take up less storage space, and will upload and download faster | ||
| 211 | +// The file should still be accessible by any HTTP client that supports gzipped responses (eg browsers, NSURLConnection, etc) | ||
| 212 | +- (void)testGZippedContent | ||
| 213 | +{ | ||
| 214 | + // Create the file | ||
| 215 | + NSString *text = @"This is my content This is my content This is my content This is my content This is my content This is my content"; | ||
| 216 | + NSString *filePath = [[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"testfile.txt"]; | ||
| 217 | + [[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO]; | ||
| 218 | + | ||
| 219 | + NSString *path = @"/gzipped-data"; | ||
| 220 | + ASIS3Request *request = [ASIS3Request PUTRequestForFile:filePath withBucket:bucket path:path]; | ||
| 221 | + [request setSecretAccessKey:secretAccessKey]; | ||
| 222 | + [request setAccessKey:accessKey]; | ||
| 223 | + [request setShouldCompressRequestBody:YES]; | ||
| 224 | + [request setAccessPolicy:ASIS3AccessPolicyPublicRead]; // We'll make it public | ||
| 225 | + [request start]; | ||
| 226 | + BOOL success = [[request responseString] isEqualToString:@""]; | ||
| 227 | + GHAssertTrue(success,@"Failed to PUT the gzipped file"); | ||
| 228 | + | ||
| 229 | + // GET the file | ||
| 230 | + request = [ASIS3Request requestWithBucket:bucket path:path]; | ||
| 231 | + [request setSecretAccessKey:secretAccessKey]; | ||
| 232 | + [request setAccessKey:accessKey]; | ||
| 233 | + [request start]; | ||
| 234 | + success = [[request responseString] isEqualToString:text]; | ||
| 235 | + GHAssertTrue(success,@"Failed to GET the correct data from S3"); | ||
| 236 | + | ||
| 237 | + success = [[[request responseHeaders] valueForKey:@"Content-Encoding"] isEqualToString:@"gzip"]; | ||
| 238 | + GHAssertTrue(success,@"Failed to GET the correct data from S3"); | ||
| 239 | + | ||
| 240 | + // Now grab the data using something other than ASIHTTPRequest to ensure other HTTP clients can parse the gzipped content | ||
| 241 | + NSData *data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.s3.amazonaws.com/gzipped-data",bucket]]] returningResponse:NULL error:NULL]; | ||
| 242 | + NSString *string = [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding] autorelease]; | ||
| 243 | + success = [string isEqualToString:text]; | ||
| 244 | + GHAssertTrue(success,@"Failed to GET the correct data from S3"); | ||
| 245 | + | ||
| 246 | +} | ||
| 247 | + | ||
| 248 | + | ||
| 208 | - (void)testListRequest | 249 | - (void)testListRequest |
| 209 | { | 250 | { |
| 210 | 251 |
-
Please register or login to post a comment