Ben Copsey

Make resume work when redirecting

@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 #import "ASIInputStream.h" 21 #import "ASIInputStream.h"
22 22
23 // Automatically set on build 23 // Automatically set on build
24 -NSString *ASIHTTPRequestVersion = @"v1.5-51 2010-03-02"; 24 +NSString *ASIHTTPRequestVersion = @"v1.5-52 2010-03-02";
25 25
26 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; 26 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
27 27
@@ -2498,6 +2498,11 @@ static BOOL isiPhoneOS2; @@ -2498,6 +2498,11 @@ static BOOL isiPhoneOS2;
2498 // For bandwidth measurement / throttling 2498 // For bandwidth measurement / throttling
2499 [ASIHTTPRequest incrementBandwidthUsedInLastSecond:bytesRead]; 2499 [ASIHTTPRequest incrementBandwidthUsedInLastSecond:bytesRead];
2500 2500
  2501 + // If we need to redirect, and have automatic redirect on, and might be resuming a download, let's do nothing with the content
  2502 + if ([self needsRedirect] && [self shouldRedirect] && [self allowResumeForFileDownloads]) {
  2503 + return;
  2504 + }
  2505 +
2501 // Are we downloading to a file? 2506 // Are we downloading to a file?
2502 if ([self downloadDestinationPath]) { 2507 if ([self downloadDestinationPath]) {
2503 if (![self fileDownloadOutputStream]) { 2508 if (![self fileDownloadOutputStream]) {
@@ -2554,15 +2559,19 @@ static BOOL isiPhoneOS2; @@ -2554,15 +2559,19 @@ static BOOL isiPhoneOS2;
2554 [[self fileDownloadOutputStream] close]; 2559 [[self fileDownloadOutputStream] close];
2555 [self setFileDownloadOutputStream:nil]; 2560 [self setFileDownloadOutputStream:nil];
2556 2561
  2562 + // If we are going to redirect and we are resuming, let's ignore this download
  2563 + if ([self shouldRedirect] && [self needsRedirect] && [self allowResumeForFileDownloads]) {
  2564 +
2557 // Decompress the file (if necessary) directly to the destination path 2565 // Decompress the file (if necessary) directly to the destination path
2558 - if ([self isResponseCompressed]) { 2566 + } else if ([self isResponseCompressed]) {
2559 int decompressionStatus = [ASIHTTPRequest uncompressZippedDataFromFile:[self temporaryFileDownloadPath] toFile:[self downloadDestinationPath]]; 2567 int decompressionStatus = [ASIHTTPRequest uncompressZippedDataFromFile:[self temporaryFileDownloadPath] toFile:[self downloadDestinationPath]];
2560 if (decompressionStatus != Z_OK) { 2568 if (decompressionStatus != Z_OK) {
2561 fileError = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Decompression of %@ failed with code %hi",[self temporaryFileDownloadPath],decompressionStatus],NSLocalizedDescriptionKey,nil]]; 2569 fileError = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Decompression of %@ failed with code %hi",[self temporaryFileDownloadPath],decompressionStatus],NSLocalizedDescriptionKey,nil]];
2562 } 2570 }
2563 [self removeTemporaryDownloadFile]; 2571 [self removeTemporaryDownloadFile];
2564 } else { 2572 } else {
2565 - 2573 +
  2574 +
2566 //Remove any file at the destination path 2575 //Remove any file at the destination path
2567 NSError *moveError = nil; 2576 NSError *moveError = nil;
2568 if ([[NSFileManager defaultManager] fileExistsAtPath:[self downloadDestinationPath]]) { 2577 if ([[NSFileManager defaultManager] fileExistsAtPath:[self downloadDestinationPath]]) {
@@ -449,6 +449,60 @@ @@ -449,6 +449,60 @@
449 } 449 }
450 } 450 }
451 451
  452 +- (void)testRedirectedResume
  453 +{
  454 + [self performSelectorOnMainThread:@selector(runRedirectedResume) withObject:nil waitUntilDone:YES];
  455 +}
  456 +
  457 +- (void)runRedirectedResume
  458 +{
  459 + NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect_resume"];
  460 + NSString *temporaryPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"foo.temp"];
  461 +
  462 + [@"" writeToFile:temporaryPath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
  463 +
  464 + NSString *downloadPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"foo.txt"];
  465 +
  466 + // Download part of a large file that is returned after a redirect
  467 + ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
  468 + [request setTemporaryFileDownloadPath:temporaryPath];
  469 + [request setDownloadDestinationPath:downloadPath];
  470 + [request setAllowResumeForFileDownloads:YES];
  471 + [request setAllowCompressedResponse:NO];
  472 + [request startAsynchronous];
  473 +
  474 + // Cancel the request as soon as it has downloaded 64KB
  475 + while (1) {
  476 + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
  477 + if ([request totalBytesRead] > 32*1024) {
  478 + [request cancel];
  479 + break;
  480 + }
  481 + }
  482 + NSNumber *fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:temporaryPath error:NULL] objectForKey:NSFileSize];
  483 + unsigned long long partialFileSize = [fileSize unsignedLongLongValue];
  484 + BOOL success = (partialFileSize < 1036935);
  485 + GHAssertTrue(success,@"Downloaded whole file too quickly, cannot proceed with this test");
  486 +
  487 +
  488 +
  489 + // Resume the download synchronously
  490 + request = [ASIHTTPRequest requestWithURL:url];
  491 + [request setTemporaryFileDownloadPath:temporaryPath];
  492 + [request setDownloadDestinationPath:downloadPath];
  493 + [request setAllowResumeForFileDownloads:YES];
  494 + [request setAllowCompressedResponse:NO];
  495 + [request startSynchronous];
  496 +
  497 + fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:downloadPath error:NULL] objectForKey:NSFileSize];
  498 + success = ([fileSize intValue] == 1036935);
  499 + GHAssertTrue(success,@"Downloaded file has wrong length");
  500 +
  501 + success = [[[request requestHeaders] objectForKey:@"Range"] isEqualToString:[NSString stringWithFormat:@"bytes=%llu-",partialFileSize]];
  502 + GHAssertTrue(success,@"Restarted download when we should have resumed, or asked for the wrong segment of the file");
  503 +
  504 +}
  505 +
452 - (void)testUploadContentLength 506 - (void)testUploadContentLength
453 { 507 {
454 //This url will return the contents of the Content-Length request header 508 //This url will return the contents of the Content-Length request header