Ben Copsey

Start work on download cache

//
// ASICacheDelegate.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 01/05/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
@class ASIHTTPRequest;
typedef enum _ASICachePolicy {
ASIDefaultCachePolicy = 0,
ASIIgnoreCachePolicy = 1,
ASIReloadIfDifferentCachePolicy = 2,
ASIOnlyLoadIfNotCachedCachePolicy = 3,
ASIUseCacheIfLoadFailsCachePolicy = 4
} ASICachePolicy;
typedef enum _ASICacheStoragePolicy {
ASICacheForSessionDurationCacheStoragePolicy = 0,
ASICachePermanentlyCacheStoragePolicy = 1
} ASICacheStoragePolicy;
@protocol ASICacheDelegate <NSObject>
@required
- (BOOL)useDataFromCacheForRequest:(ASIHTTPRequest *)request;
- (void)storeResponseForRequest:(ASIHTTPRequest *)request;
- (NSDictionary *)cachedHeadersForRequest:(ASIHTTPRequest *)request;
- (NSData *)cachedResponseDataForRequest:(ASIHTTPRequest *)request;
- (NSString *)pathToCachedResponseDataForRequest:(ASIHTTPRequest *)request;
- (void)clearCachedResponsesForStoragePolicy:(ASICacheStoragePolicy)cachePolicy;
@end
... ...
//
// ASIDownloadCache.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 01/05/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASICacheDelegate.h"
@interface ASIDownloadCache : NSObject <ASICacheDelegate> {
ASICachePolicy defaultCachePolicy;
ASICacheStoragePolicy defaultCacheStoragePolicy;
NSString *storagePath;
NSLock *accessLock;
BOOL shouldRespectCacheHeaders;
}
+ (id)sharedCache;
+ (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request;
@property (assign) ASICachePolicy defaultCachePolicy;
@property (assign) ASICacheStoragePolicy defaultCacheStoragePolicy;
@property (retain) NSString *storagePath;
@property (retain) NSLock *accessLock;
@property (assign) BOOL shouldRespectCacheHeaders;
@end
... ...
This diff is collapsed. Click to expand it.
... ... @@ -18,6 +18,7 @@
#import "ASIHTTPRequestConfig.h"
#import "ASIHTTPRequestDelegate.h"
#import "ASIProgressDelegate.h"
#import "ASICacheDelegate.h"
extern NSString *ASIHTTPRequestVersion;
... ... @@ -389,6 +390,16 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
// Will be ASIHTTPRequestRunLoopMode for synchronous requests, NSDefaultRunLoopMode for all other requests
NSString *runLoopMode;
// The download cache that will be used for this request (use [ASIHTTPRequest setDefaultCache:cache] to configure a default cache
id <ASICacheDelegate> downloadCache;
// The cache policy that will be used for this request - See ASICacheDelegate.h for possible values
ASICachePolicy cachePolicy;
// The cache storage policy that will be used for this request - See ASICacheDelegate.h for possible values
ASICacheStoragePolicy cacheStoragePolicy;
}
#pragma mark init / dealloc
... ... @@ -399,6 +410,9 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
// Convenience constructor
+ (id)requestWithURL:(NSURL *)newURL;
+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache;
+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache andCachePolicy:(ASICachePolicy)policy;
#pragma mark setup request
// Add a custom header to the request
... ... @@ -668,6 +682,11 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
#endif
#pragma mark cache
+ (void)setDefaultCache:(id <ASICacheDelegate>)cache;
+ (id <ASICacheDelegate>)defaultCache;
// Returns the maximum amount of data we can read as part of the current measurement period, and sleeps this thread if our allowance is used up
+ (unsigned long)maxUploadReadLength;
... ... @@ -712,7 +731,7 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
@property (retain,readonly) NSString *proxyAuthenticationRealm;
@property (retain) NSError *error;
@property (assign,readonly) BOOL complete;
@property (retain,readonly) NSDictionary *responseHeaders;
@property (retain) NSDictionary *responseHeaders;
@property (retain) NSMutableDictionary *requestHeaders;
@property (retain) NSMutableArray *requestCookies;
@property (retain,readonly) NSArray *responseCookies;
... ... @@ -721,7 +740,7 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
@property (retain) NSDictionary *proxyCredentials;
@property (assign,readonly) int responseStatusCode;
@property (retain,readonly) NSString *responseStatusMessage;
@property (retain,readonly) NSMutableData *rawResponseData;
@property (retain) NSMutableData *rawResponseData;
@property (assign) NSTimeInterval timeOutSeconds;
@property (retain) NSString *requestMethod;
@property (retain) NSMutableData *postBody;
... ... @@ -766,4 +785,7 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
@property (assign) BOOL shouldUseRFC2616RedirectBehaviour;
@property (assign, readonly) BOOL connectionCanBeReused;
@property (retain, readonly) NSNumber *requestID;
@property (assign) id <ASICacheDelegate> downloadCache;
@property (assign) ASICachePolicy cachePolicy;
@property (assign) ASICacheStoragePolicy cacheStoragePolicy;
@end
... ...
... ... @@ -23,7 +23,7 @@
// Automatically set on build
NSString *ASIHTTPRequestVersion = @"v1.6.2-8 2010-05-01";
NSString *ASIHTTPRequestVersion = @"v1.6.2-9 2010-05-02";
NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
... ... @@ -121,6 +121,8 @@ static NSDate *throttleWakeUpTime = nil;
// Run once in initalize to record at runtime whether we're on iPhone OS 2. When YES, a workaround for a type conversion bug in iPhone OS 2.2.x is applied in some places
static BOOL isiPhoneOS2;
static id <ASICacheDelegate> defaultCache = nil;
// Private stuff
@interface ASIHTTPRequest ()
... ... @@ -151,10 +153,8 @@ static BOOL isiPhoneOS2;
#endif
@property (assign) BOOL complete;
@property (retain) NSDictionary *responseHeaders;
@property (retain) NSArray *responseCookies;
@property (assign) int responseStatusCode;
@property (retain) NSMutableData *rawResponseData;
@property (retain, nonatomic) NSDate *lastActivityTime;
@property (assign) unsigned long long contentLength;
@property (assign) unsigned long long partialDownloadSize;
... ... @@ -252,6 +252,7 @@ static BOOL isiPhoneOS2;
[self setDidReceiveDataSelector:@selector(request:didReceiveData:)];
[self setURL:newURL];
[self setCancelledLock:[[[NSRecursiveLock alloc] init] autorelease]];
[self setDownloadCache:[[self class] defaultCache]];
return self;
}
... ... @@ -260,6 +261,19 @@ static BOOL isiPhoneOS2;
return [[[self alloc] initWithURL:newURL] autorelease];
}
+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache
{
return [self requestWithURL:newURL usingCache:cache andCachePolicy:ASIDefaultCachePolicy];
}
+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache andCachePolicy:(ASICachePolicy)policy
{
ASIHTTPRequest *request = [[[self alloc] initWithURL:newURL] autorelease];
[request setDownloadCache:cache];
[request setCachePolicy:policy];
return request;
}
- (void)dealloc
{
[statusTimer invalidate];
... ... @@ -607,6 +621,10 @@ static BOOL isiPhoneOS2;
[self buildPostBody];
}
if (![[self requestMethod] isEqualToString:@"GET"]) {
[self setDownloadCache:nil];
}
// If we're redirecting, we'll already have a CFHTTPMessageRef
if (request) {
CFRelease(request);
... ... @@ -780,6 +798,15 @@ static BOOL isiPhoneOS2;
return;
}
// See if we should pull from the cache rather than fetching the data
if ([self downloadCache] && [self cachePolicy] == ASIOnlyLoadIfNotCachedCachePolicy) {
if ([[self downloadCache] useDataFromCacheForRequest:self]) {
[[self cancelledLock] unlock];
return;
}
}
[self requestStarted];
[self setDownloadComplete:NO];
... ... @@ -1545,6 +1572,17 @@ static BOOL isiPhoneOS2;
return;
}
if ([self downloadCache] && [self cachePolicy] == ASIUseCacheIfLoadFailsCachePolicy) {
if ([[self downloadCache] useDataFromCacheForRequest:self]) {
[self markAsFinished];
if ([self mainRequest]) {
[[self mainRequest] markAsFinished];
}
return;
}
}
[self setError:theError];
ASIHTTPRequest *failedRequest = self;
... ... @@ -1598,6 +1636,17 @@ static BOOL isiPhoneOS2;
[self setResponseHeaders:(NSDictionary *)headerFields];
CFRelease(headerFields);
if ([self downloadCache] && [self cachePolicy] == ASIReloadIfDifferentCachePolicy) {
if ([[self downloadCache] useDataFromCacheForRequest:self]) {
CFRelease(message);
[self cancelLoad];
[self markAsFinished];
return;
}
}
[self setResponseStatusCode:(int)CFHTTPMessageGetResponseStatusCode(message)];
[self setResponseStatusMessage:[(NSString *)CFHTTPMessageCopyResponseStatusLine(message) autorelease]];
... ... @@ -2569,6 +2618,12 @@ static BOOL isiPhoneOS2;
}
}
// Save to the cache
if ([self downloadCache]) {
[[self downloadCache] storeResponseForRequest:self];
}
[progressLock unlock];
... ... @@ -3001,6 +3056,7 @@ static BOOL isiPhoneOS2;
[[[self class] sessionCredentialsStore] removeAllObjects];
[sessionCredentialsLock unlock];
[[self class] setSessionCookies:nil];
[[[self class] defaultCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
}
#pragma mark gzip decompression
... ... @@ -3617,6 +3673,18 @@ static BOOL isiPhoneOS2;
#endif
+ (void)setDefaultCache:(id <ASICacheDelegate>)cache
{
[defaultCache release];
defaultCache = [cache retain];
}
+ (id <ASICacheDelegate>)defaultCache
{
return defaultCache;
}
#pragma mark miscellany
+ (BOOL)isiPhoneOS2
... ... @@ -3761,4 +3829,7 @@ static BOOL isiPhoneOS2;
@synthesize downloadComplete;
@synthesize requestID;
@synthesize runLoopMode;
@synthesize downloadCache;
@synthesize cachePolicy;
@synthesize cacheStoragePolicy;
@end
... ...
This diff was suppressed by a .gitattributes entry.