Skip to content

Instantly share code, notes, and snippets.

@angelolloqui
Created August 15, 2012 14:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angelolloqui/3360769 to your computer and use it in GitHub Desktop.
Save angelolloqui/3360769 to your computer and use it in GitHub Desktop.
RestKit addition to add a new cache policy that checks the Cache-Control HTTP header
//
// RKRequest+CacheControl.h
//
// Created by Angel on 8/10/12.
// Copyright (c) 2012 Xaton. All rights reserved.
//
#import "RKRequest.h"
#define RKRequestCachePolicyControlMaxAge 1 << 7
@interface RKRequest (CacheControl)
@end
//
// RKRequest+CacheControl.m
//
// Created by Angel on 8/10/12.
// Copyright (c) 2012 Xaton. All rights reserved.
//
#import "RKRequest+CacheControl.h"
#include <objc/runtime.h>
static NSString *kHTTPCacheControl = @"Cache-Control";
@implementation RKRequest (CacheControl)
+ (void)load {
//Swizzle the original shouldLoadFromCache method to provide our own implementation
Method shouldLoadFromCacheCustom = class_getInstanceMethod([RKRequest class], @selector(shouldLoadFromCacheCustom));
Method shouldLoadFromCache = class_getInstanceMethod([RKRequest class], @selector(shouldLoadFromCache));
NSAssert(shouldLoadFromCache, @"The current version of RestKit is not compatible with the Cache-Control additions");
method_exchangeImplementations(shouldLoadFromCache, shouldLoadFromCacheCustom);
}
- (BOOL)shouldLoadFromCacheCustom {
if ([self.cache hasResponseForRequest:self]) {
if (self.cachePolicy & RKRequestCachePolicyControlMaxAge) {
NSDictionary *headers = [self.cache headersForRequest:self];
//Retrieve the Cache-Control header
NSString *cacheControl = [headers objectForKey:kHTTPCacheControl];
if (!cacheControl) {
//Check for lower case headers that could also match
for (NSString* responseHeader in headers) {
if ([[responseHeader uppercaseString] isEqualToString:[kHTTPCacheControl uppercaseString]]) {
cacheControl = [headers objectForKey:responseHeader];
break;
}
}
}
if (cacheControl) {
//Check the cache control max age
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\bmax-age=(\\d)+"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:cacheControl options:0 range:NSMakeRange(0, [cacheControl length])];
if (rangeOfFirstMatch.location != NSNotFound) {
NSInteger maxAge = [[cacheControl substringWithRange:NSMakeRange(rangeOfFirstMatch.location + 8, rangeOfFirstMatch.length - 8)] integerValue];
NSDate* date = [self.cache cacheDateForRequest:self];
NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:date];
if (interval < maxAge) {
#ifdef DEBUG
NSLog(@"Reusing cached result for %@ with maxAge %d and current age %d", [self.URL absoluteString], maxAge, (NSInteger)interval);
#endif
return YES;
}
}
//Check the cache control no-cache
regex = [NSRegularExpression regularExpressionWithPattern:@"\\bno-cache\\b"
options:NSRegularExpressionCaseInsensitive
error:&error];
rangeOfFirstMatch = [regex rangeOfFirstMatchInString:cacheControl options:0 range:NSMakeRange(0, [cacheControl length])];
if (rangeOfFirstMatch.location != NSNotFound) {
return NO;
}
}
}
}
return [self shouldLoadFromCacheCustom];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment