diff --git a/Code/Network/RKRequest.m b/Code/Network/RKRequest.m index adb8b423..28d46be3 100644 --- a/Code/Network/RKRequest.m +++ b/Code/Network/RKRequest.m @@ -439,6 +439,12 @@ } } +- (void)updateInternalCacheDate { + NSDate* date = [NSDate date]; + RKLogInfo(@"Updating cache date for request %@ to %@", self, date); + [self.cache setCacheDate:date forRequest:self]; +} + - (void)didFinishLoad:(RKResponse*)response { _isLoading = NO; _isLoaded = YES; @@ -450,6 +456,7 @@ if ((_cachePolicy & RKRequestCachePolicyEtag) && [response isNotModified]) { finalResponse = [self loadResponseFromCache]; + [self updateInternalCacheDate]; } if (![response wasLoadedFromCache] && [response isSuccessful] && (_cachePolicy != RKRequestCachePolicyNone)) { @@ -535,7 +542,8 @@ if (_method == RKRequestMethodDELETE) { return nil; } - NSString* compositCacheKey = [NSString stringWithFormat:@"%@-%d-%@", self.URL, _method, [_URLRequest HTTPBody]]; + // Use [_params HTTPBody] because the URLRequest body may not have been set up yet. + NSString* compositCacheKey = [NSString stringWithFormat:@"%@-%d-%@", self.URL, _method, [_params HTTPBody]]; return [compositCacheKey MD5]; } diff --git a/Code/Network/RKRequestCache.h b/Code/Network/RKRequestCache.h index 3f9d1ad7..dd0e522a 100644 --- a/Code/Network/RKRequestCache.h +++ b/Code/Network/RKRequestCache.h @@ -50,6 +50,8 @@ typedef enum { - (NSDate*)cacheDateForRequest:(RKRequest*)request; +- (void)setCacheDate:(NSDate*)date forRequest:(RKRequest*)request; + - (void)invalidateRequest:(RKRequest*)request; - (void)invalidateWithStoragePolicy:(RKRequestCacheStoragePolicy)storagePolicy; diff --git a/Code/Network/RKRequestCache.m b/Code/Network/RKRequestCache.m index 7b4aafae..9a64313e 100644 --- a/Code/Network/RKRequestCache.m +++ b/Code/Network/RKRequestCache.m @@ -128,6 +128,19 @@ static NSDateFormatter* __rfc1123DateFormatter; return hasEntryForRequest; } +- (void)writeHeaders:(NSDictionary*)headers toCachePath:(NSString*)cachePath { + RKLogTrace(@"Writing headers to cache path: '%@'", cachePath); + BOOL success = [headers writeToFile:[cachePath + stringByAppendingPathExtension:headersExtension] + atomically:YES]; + if (success) { + RKLogTrace(@"Wrote cached response header to path '%@'", cachePath); + + } else { + RKLogError(@"Failed to write cached response headers to path '%@'", cachePath); + } +} + - (void)storeResponse:(RKResponse*)response forRequest:(RKRequest*)request { [_cacheLock lock]; @@ -166,15 +179,7 @@ static NSDateFormatter* __rfc1123DateFormatter; [headers setObject:[urlResponse.URL absoluteString] forKey:cacheURLKey]; // Save - BOOL success = [headers writeToFile:[cachePath - stringByAppendingPathExtension:headersExtension] - atomically:YES]; - if (success) { - RKLogTrace(@"Wrote cached response header to path '%@'", cachePath); - - } else { - RKLogError(@"Failed to write cached response headers to path '%@'", cachePath); - } + [self writeHeaders:headers toCachePath:cachePath]; } [headers release]; @@ -245,6 +250,16 @@ static NSDateFormatter* __rfc1123DateFormatter; return etag; } +- (void)setCacheDate:(NSDate*)date forRequest:(RKRequest*)request { + NSMutableDictionary* responseHeaders = [[self headersForRequest:request] mutableCopy]; + + [responseHeaders setObject:[[RKRequestCache rfc1123DateFormatter] stringFromDate:date] + forKey:cacheDateHeaderKey]; + [self writeHeaders:responseHeaders toCachePath:[self pathForRequest:request]]; + + [responseHeaders release]; +} + - (NSDate*)cacheDateForRequest:(RKRequest*)request { NSDate* date; NSString* dateString; diff --git a/Code/ObjectMapping/RKObjectLoader.m b/Code/ObjectMapping/RKObjectLoader.m index cfe3533c..27b80e8f 100644 --- a/Code/ObjectMapping/RKObjectLoader.m +++ b/Code/ObjectMapping/RKObjectLoader.m @@ -22,6 +22,10 @@ #undef RKLogComponent #define RKLogComponent lcl_cRestKitNetwork +@interface RKRequest (Private) +- (void)updateInternalCacheDate; +@end + @implementation RKObjectLoader @synthesize objectManager = _objectManager, response = _response; @@ -321,6 +325,7 @@ [_response release]; _response = nil; _response = [[[[RKClient sharedClient] cache] responseForRequest:self] retain]; + [self updateInternalCacheDate]; } if (![_response wasLoadedFromCache] && [_response isSuccessful] && (_cachePolicy != RKRequestCachePolicyNone)) { diff --git a/Specs/Network/RKRequestSpec.m b/Specs/Network/RKRequestSpec.m index f25619d2..5a30d1d0 100644 --- a/Specs/Network/RKRequestSpec.m +++ b/Specs/Network/RKRequestSpec.m @@ -286,6 +286,54 @@ } } +- (void)itShouldUpdateTheInternalCacheDateWhenWeRecieveA304 { + RKLogConfigureByName("RestKit/Network", RKLogLevelTrace); + NSString* baseURL = RKSpecGetBaseURL(); + NSString* cacheDirForClient = [NSString stringWithFormat:@"RKClientRequestCache-%@", + [[NSURL URLWithString:baseURL] host]]; + NSString* cachePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] + stringByAppendingPathComponent:cacheDirForClient]; + RKRequestCache* cache = [[RKRequestCache alloc] initWithCachePath:cachePath + storagePolicy:RKRequestCacheStoragePolicyPermanently]; + [cache invalidateWithStoragePolicy:RKRequestCacheStoragePolicyPermanently]; + + NSDate* internalCacheDate1; + NSDate* internalCacheDate2; + { + RKSpecResponseLoader* loader = [RKSpecResponseLoader responseLoader]; + NSString* url = [NSString stringWithFormat:@"%@/etags/cached", RKSpecGetBaseURL()]; + NSURL* URL = [NSURL URLWithString:url]; + RKRequest* request = [[RKRequest alloc] initWithURL:URL]; + request.cachePolicy = RKRequestCachePolicyEtag; + request.cache = cache; + request.delegate = loader; + [request sendAsynchronously]; + [loader waitForResponse]; + [expectThat([loader success]) should:be(YES)]; + [expectThat([loader.response bodyAsString]) should:be(@"This Should Get Cached")]; + [expectThat([cache etagForRequest:request]) should:be(@"686897696a7c876b7e")]; + [expectThat([loader.response wasLoadedFromCache]) should:be(NO)]; + internalCacheDate1 = [cache cacheDateForRequest:request]; + } + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.5]]; + { + RKSpecResponseLoader* loader = [RKSpecResponseLoader responseLoader]; + NSString* url = [NSString stringWithFormat:@"%@/etags/cached", RKSpecGetBaseURL()]; + NSURL* URL = [NSURL URLWithString:url]; + RKRequest* request = [[RKRequest alloc] initWithURL:URL]; + request.cachePolicy = RKRequestCachePolicyEtag; + request.cache = cache; + request.delegate = loader; + [request sendAsynchronously]; + [loader waitForResponse]; + [expectThat([loader success]) should:be(YES)]; + [expectThat([loader.response bodyAsString]) should:be(@"This Should Get Cached")]; + [expectThat([loader.response wasLoadedFromCache]) should:be(YES)]; + internalCacheDate2 = [cache cacheDateForRequest:request]; + } + [expectThat(internalCacheDate1) shouldNot:be(internalCacheDate2)]; +} + - (void)itShouldLoadFromTheCacheIfThereIsAnError { NSString* baseURL = RKSpecGetBaseURL(); NSString* cacheDirForClient = [NSString stringWithFormat:@"RKClientRequestCache-%@", @@ -325,8 +373,6 @@ } - (void)itShouldLoadFromTheCacheIfWeAreWithinTheTimeout { - RKLogConfigureByName("RestKit/Network", RKLogLevelTrace); - NSString* baseURL = RKSpecGetBaseURL(); NSString* cacheDirForClient = [NSString stringWithFormat:@"RKClientRequestCache-%@", [[NSURL URLWithString:baseURL] host]];