Ben Copsey

We now dump all cookies on redirection (cookies stored in the peristent store will be re-applied)

Fix memory leak on redirection

Thanks to Austin France for highlighting these issues!
@@ -319,13 +319,15 @@ extern NSString* const NetworkRequestErrorDomain; @@ -319,13 +319,15 @@ extern NSString* const NetworkRequestErrorDomain;
319 // Called when a request fails, and lets the delegate now via didFailSelector 319 // Called when a request fails, and lets the delegate now via didFailSelector
320 - (void)failWithError:(NSError *)theError; 320 - (void)failWithError:(NSError *)theError;
321 321
322 -#pragma mark http authentication stuff 322 +#pragma mark parsing HTTP response headers
323 323
324 // Reads the response headers to find the content length, encoding, cookies for the session 324 // Reads the response headers to find the content length, encoding, cookies for the session
325 // Also initiates request redirection when shouldRedirect is true 325 // Also initiates request redirection when shouldRedirect is true
326 // Returns true if the request needs a username and password (or if those supplied were incorrect) 326 // Returns true if the request needs a username and password (or if those supplied were incorrect)
327 - (BOOL)readResponseHeadersReturningAuthenticationFailure; 327 - (BOOL)readResponseHeadersReturningAuthenticationFailure;
328 328
  329 +#pragma mark http authentication stuff
  330 +
329 // Apply credentials to this request 331 // Apply credentials to this request
330 - (BOOL)applyCredentials:(NSMutableDictionary *)newCredentials; 332 - (BOOL)applyCredentials:(NSMutableDictionary *)newCredentials;
331 333
@@ -206,8 +206,7 @@ static NSError *ASITooMuchRedirectionError; @@ -206,8 +206,7 @@ static NSError *ASITooMuchRedirectionError;
206 } 206 }
207 } 207 }
208 208
209 - if ([self postLength] > 0) 209 + if ([self postLength] > 0) {
210 - {  
211 if (![requestMethod isEqualToString:@"POST"] && ![requestMethod isEqualToString:@"PUT"]) { 210 if (![requestMethod isEqualToString:@"POST"] && ![requestMethod isEqualToString:@"PUT"]) {
212 [self setRequestMethod:@"POST"]; 211 [self setRequestMethod:@"POST"];
213 } 212 }
@@ -339,8 +338,13 @@ static NSError *ASITooMuchRedirectionError; @@ -339,8 +338,13 @@ static NSError *ASITooMuchRedirectionError;
339 [self buildPostBody]; 338 [self buildPostBody];
340 } 339 }
341 340
  341 + // If we're redirecting, we'll already have a CFHTTPMessageRef
  342 + if (request) {
  343 + CFRelease(request);
  344 + }
  345 +
342 // Create a new HTTP request. 346 // Create a new HTTP request.
343 - request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)requestMethod, (CFURLRef)url, [self useHTTPVersionOne] ? kCFHTTPVersion1_0 : kCFHTTPVersion1_1); 347 + request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)[self requestMethod], (CFURLRef)[self url], [self useHTTPVersionOne] ? kCFHTTPVersion1_0 : kCFHTTPVersion1_1);
344 if (!request) { 348 if (!request) {
345 [self failWithError:ASIUnableToCreateRequestError]; 349 [self failWithError:ASIUnableToCreateRequestError];
346 return; 350 return;
@@ -348,7 +352,7 @@ static NSError *ASITooMuchRedirectionError; @@ -348,7 +352,7 @@ static NSError *ASITooMuchRedirectionError;
348 352
349 353
350 // If we've already talked to this server and have valid credentials, let's apply them to the request 354 // If we've already talked to this server and have valid credentials, let's apply them to the request
351 - if (useSessionPersistance && sessionCredentials && sessionAuthentication) { 355 + if ([self useSessionPersistance] && sessionCredentials && sessionAuthentication) {
352 if (!CFHTTPMessageApplyCredentialDictionary(request, sessionAuthentication, (CFMutableDictionaryRef)sessionCredentials, NULL)) { 356 if (!CFHTTPMessageApplyCredentialDictionary(request, sessionAuthentication, (CFMutableDictionaryRef)sessionCredentials, NULL)) {
353 [ASIHTTPRequest setSessionAuthentication:NULL]; 357 [ASIHTTPRequest setSessionAuthentication:NULL];
354 [ASIHTTPRequest setSessionCredentials:nil]; 358 [ASIHTTPRequest setSessionCredentials:nil];
@@ -356,10 +360,10 @@ static NSError *ASITooMuchRedirectionError; @@ -356,10 +360,10 @@ static NSError *ASITooMuchRedirectionError;
356 } 360 }
357 361
358 // Add cookies from the persistant (mac os global) store 362 // Add cookies from the persistant (mac os global) store
359 - if (useCookiePersistance) { 363 + if ([self useCookiePersistance] ) {
360 - NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url]; 364 + NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[self url]];
361 if (cookies) { 365 if (cookies) {
362 - [requestCookies addObjectsFromArray:cookies]; 366 + [[self requestCookies] addObjectsFromArray:cookies];
363 } 367 }
364 } 368 }
365 369
@@ -399,7 +403,7 @@ static NSError *ASITooMuchRedirectionError; @@ -399,7 +403,7 @@ static NSError *ASITooMuchRedirectionError;
399 // Should this request resume an existing download? 403 // Should this request resume an existing download?
400 if ([self allowResumeForFileDownloads] && [self downloadDestinationPath] && [self temporaryFileDownloadPath] && [[NSFileManager defaultManager] fileExistsAtPath:[self temporaryFileDownloadPath]]) { 404 if ([self allowResumeForFileDownloads] && [self downloadDestinationPath] && [self temporaryFileDownloadPath] && [[NSFileManager defaultManager] fileExistsAtPath:[self temporaryFileDownloadPath]]) {
401 [self setPartialDownloadSize:[[[NSFileManager defaultManager] fileAttributesAtPath:[self temporaryFileDownloadPath] traverseLink:NO] fileSize]]; 405 [self setPartialDownloadSize:[[[NSFileManager defaultManager] fileAttributesAtPath:[self temporaryFileDownloadPath] traverseLink:NO] fileSize]];
402 - [self addRequestHeader:@"Range" value:[NSString stringWithFormat:@"bytes=%llu-",partialDownloadSize]]; 406 + [self addRequestHeader:@"Range" value:[NSString stringWithFormat:@"bytes=%llu-",[self partialDownloadSize]]];
403 } 407 }
404 408
405 // Add custom headers 409 // Add custom headers
@@ -413,7 +417,7 @@ static NSError *ASITooMuchRedirectionError; @@ -413,7 +417,7 @@ static NSError *ASITooMuchRedirectionError;
413 } 417 }
414 NSString *header; 418 NSString *header;
415 for (header in headers) { 419 for (header in headers) {
416 - CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[requestHeaders objectForKey:header]); 420 + CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[[self requestHeaders] objectForKey:header]);
417 } 421 }
418 422
419 // If this is a post/put request and we store the request body in memory, add it to the request 423 // If this is a post/put request and we store the request body in memory, add it to the request
@@ -986,8 +990,7 @@ static NSError *ASITooMuchRedirectionError; @@ -986,8 +990,7 @@ static NSError *ASITooMuchRedirectionError;
986 } 990 }
987 } 991 }
988 992
989 - 993 +#pragma mark parsing HTTP response headers
990 -#pragma mark http authentication  
991 994
992 - (BOOL)readResponseHeadersReturningAuthenticationFailure 995 - (BOOL)readResponseHeadersReturningAuthenticationFailure
993 { 996 {
@@ -1069,6 +1072,11 @@ static NSError *ASITooMuchRedirectionError; @@ -1069,6 +1072,11 @@ static NSError *ASITooMuchRedirectionError;
1069 } 1072 }
1070 [self setURL:[[NSURL URLWithString:[responseHeaders valueForKey:@"Location"] relativeToURL:[self url]] absoluteURL]]; 1073 [self setURL:[[NSURL URLWithString:[responseHeaders valueForKey:@"Location"] relativeToURL:[self url]] absoluteURL]];
1071 [self setNeedsRedirect:YES]; 1074 [self setNeedsRedirect:YES];
  1075 +
  1076 + // Clear the request cookies
  1077 + // This means manually added cookies will not be added to the redirect request - only those stored in the global persistent store
  1078 + // But, this is probably the safest option - we might be redirecting to a different domain
  1079 + [self setRequestCookies:[NSMutableArray array]];
1072 } 1080 }
1073 } 1081 }
1074 1082
@@ -1079,6 +1087,7 @@ static NSError *ASITooMuchRedirectionError; @@ -1079,6 +1087,7 @@ static NSError *ASITooMuchRedirectionError;
1079 return isAuthenticationChallenge; 1087 return isAuthenticationChallenge;
1080 } 1088 }
1081 1089
  1090 +#pragma mark http authentication
1082 1091
1083 - (void)saveCredentialsToKeychain:(NSMutableDictionary *)newCredentials 1092 - (void)saveCredentialsToKeychain:(NSMutableDictionary *)newCredentials
1084 { 1093 {
@@ -744,6 +744,7 @@ @@ -744,6 +744,7 @@
744 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class"); 744 GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
745 } 745 }
746 746
  747 +
747 @end 748 @end
748 749
749 750