Ben Copsey

Make ASIReloadIfDifferentCachePolicy turn requests into conditional GETs

Stop wasting time insensitive matching response headers, CFNetwork will normalise the case for us anyway
@@ -17,7 +17,6 @@ static NSString *permanentCacheFolder = @"PermanentStore"; @@ -17,7 +17,6 @@ static NSString *permanentCacheFolder = @"PermanentStore";
17 17
18 @interface ASIDownloadCache () 18 @interface ASIDownloadCache ()
19 + (NSString *)keyForRequest:(ASIHTTPRequest *)request; 19 + (NSString *)keyForRequest:(ASIHTTPRequest *)request;
20 -+ (NSString *)responseHeader:(NSString *)header fromHeaders:(NSDictionary *)headers;  
21 @end 20 @end
22 21
23 @implementation ASIDownloadCache 22 @implementation ASIDownloadCache
@@ -185,9 +184,9 @@ static NSString *permanentCacheFolder = @"PermanentStore"; @@ -185,9 +184,9 @@ static NSString *permanentCacheFolder = @"PermanentStore";
185 return NO; 184 return NO;
186 } 185 }
187 // If the Etag or Last-Modified date are different from the one we have, fetch the document again 186 // If the Etag or Last-Modified date are different from the one we have, fetch the document again
188 - NSArray *headersToCompare = [NSArray arrayWithObjects:@"etag",@"last-modified",nil]; 187 + NSArray *headersToCompare = [NSArray arrayWithObjects:@"Etag",@"Last-Modified",nil];
189 for (NSString *header in headersToCompare) { 188 for (NSString *header in headersToCompare) {
190 - if (![[[self class] responseHeader:header fromHeaders:[request responseHeaders]] isEqualToString:[[self class] responseHeader:header fromHeaders:cachedHeaders]]) { 189 + if (![[[request responseHeaders] objectForKey:header] isEqualToString:[cachedHeaders objectForKey:header]]) {
191 return NO; 190 return NO;
192 } 191 }
193 } 192 }
@@ -195,14 +194,14 @@ static NSString *permanentCacheFolder = @"PermanentStore"; @@ -195,14 +194,14 @@ static NSString *permanentCacheFolder = @"PermanentStore";
195 return YES; 194 return YES;
196 } 195 }
197 // Look for an Expires header to see if the content is out of data 196 // Look for an Expires header to see if the content is out of data
198 - NSString *expires = [[self class] responseHeader:@"expires" fromHeaders:cachedHeaders]; 197 + NSString *expires = [cachedHeaders objectForKey:@"Expires"];
199 if (expires) { 198 if (expires) {
200 if ([[ASIHTTPRequest dateFromRFC1123String:expires] timeIntervalSinceNow] < 0) { 199 if ([[ASIHTTPRequest dateFromRFC1123String:expires] timeIntervalSinceNow] < 0) {
201 return NO; 200 return NO;
202 } 201 }
203 } 202 }
204 // Look for a max-age header 203 // Look for a max-age header
205 - NSString *cacheControl = [[[self class] responseHeader:@"cache-control" fromHeaders:cachedHeaders] lowercaseString]; 204 + NSString *cacheControl = [[cachedHeaders objectForKey:@"Cache-Control"] lowercaseString];
206 if (cacheControl) { 205 if (cacheControl) {
207 NSScanner *scanner = [NSScanner scannerWithString:cacheControl]; 206 NSScanner *scanner = [NSScanner scannerWithString:cacheControl];
208 if ([scanner scanString:@"max-age" intoString:NULL]) { 207 if ([scanner scanString:@"max-age" intoString:NULL]) {
@@ -277,13 +276,13 @@ static NSString *permanentCacheFolder = @"PermanentStore"; @@ -277,13 +276,13 @@ static NSString *permanentCacheFolder = @"PermanentStore";
277 276
278 + (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request 277 + (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request
279 { 278 {
280 - NSString *cacheControl = [[[self class] responseHeader:@"cache-control" fromHeaders:[request responseHeaders]] lowercaseString]; 279 + NSString *cacheControl = [[[request responseHeaders] objectForKey:@"Cache-Control"] lowercaseString];
281 if (cacheControl) { 280 if (cacheControl) {
282 if ([cacheControl isEqualToString:@"no-cache"] || [cacheControl isEqualToString:@"no-store"]) { 281 if ([cacheControl isEqualToString:@"no-cache"] || [cacheControl isEqualToString:@"no-store"]) {
283 return NO; 282 return NO;
284 } 283 }
285 } 284 }
286 - NSString *pragma = [[[self class] responseHeader:@"pragma" fromHeaders:[request responseHeaders]] lowercaseString]; 285 + NSString *pragma = [[[request responseHeaders] objectForKey:@"Pragma"] lowercaseString];
287 if (pragma) { 286 if (pragma) {
288 if ([pragma isEqualToString:@"no-cache"]) { 287 if ([pragma isEqualToString:@"no-cache"]) {
289 return NO; 288 return NO;
@@ -301,15 +300,6 @@ static NSString *permanentCacheFolder = @"PermanentStore"; @@ -301,15 +300,6 @@ static NSString *permanentCacheFolder = @"PermanentStore";
301 return [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],result[8], result[9], result[10], result[11],result[12], result[13], result[14], result[15]]; 300 return [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],result[8], result[9], result[10], result[11],result[12], result[13], result[14], result[15]];
302 } 301 }
303 302
304 -+ (NSString *)responseHeader:(NSString *)header fromHeaders:(NSDictionary *)headers  
305 -{  
306 - for (NSString *responseHeader in headers) {  
307 - if ([[responseHeader lowercaseString] isEqualToString:header]) {  
308 - return [headers objectForKey:responseHeader];  
309 - }  
310 - }  
311 - return nil;  
312 -}  
313 303
314 @synthesize storagePath; 304 @synthesize storagePath;
315 @synthesize defaultCachePolicy; 305 @synthesize defaultCachePolicy;
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 23
24 24
25 // Automatically set on build 25 // Automatically set on build
26 -NSString *ASIHTTPRequestVersion = @"v1.6.2-13 2010-05-03"; 26 +NSString *ASIHTTPRequestVersion = @"v1.6.2-14 2010-05-03";
27 27
28 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; 28 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
29 29
@@ -812,6 +812,21 @@ static id <ASICacheDelegate> defaultCache = nil; @@ -812,6 +812,21 @@ static id <ASICacheDelegate> defaultCache = nil;
812 [[self cancelledLock] unlock]; 812 [[self cancelledLock] unlock];
813 return; 813 return;
814 } 814 }
  815 + } else if ([self cachePolicy] == ASIReloadIfDifferentCachePolicy) {
  816 +
  817 + // Force a conditional GET if we have a cached version of this content already
  818 + NSDictionary *cachedHeaders = [[self downloadCache] cachedHeadersForRequest:self];
  819 + if (cachedHeaders) {
  820 + NSString *etag = [cachedHeaders objectForKey:@"Etag"];
  821 + if (etag) {
  822 + [[self requestHeaders] setObject:etag forKey:@"If-None-Match"];
  823 + } else {
  824 + NSString *lastModified = [cachedHeaders objectForKey:@"Last-Modified"];
  825 + if (lastModified) {
  826 + [[self requestHeaders] setObject:lastModified forKey:@"If-Modified-Since"];
  827 + }
  828 + }
  829 + }
815 } 830 }
816 } 831 }
817 832