Cédric Luthi

Merge branch 'master' of git://github.com/pokeb/asi-http-request

... ... @@ -56,9 +56,16 @@ typedef enum _ASICacheStoragePolicy {
// Should return the cache policy that will be used when requests have their cache policy set to ASIUseDefaultCachePolicy
- (ASICachePolicy)defaultCachePolicy;
// Returns the date a cached response should expire on. Pass a non-zero max age to specify a custom date.
- (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;
// Updates cached response headers with a new expiry date. Pass a non-zero max age to specify a custom date.
- (void)updateExpiryForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;
// Looks at the request's cache policy and any cached headers to determine if the cache data is still valid
- (BOOL)canUseCachedDataForRequest:(ASIHTTPRequest *)request;
// Should Remove cached data for a particular request
// Removes cached data for a particular request
- (void)removeCachedDataForRequest:(ASIHTTPRequest *)request;
// Should return YES if the cache considers its cached response current for the request
... ... @@ -69,6 +76,9 @@ typedef enum _ASICacheStoragePolicy {
// When a non-zero maxAge is passed, it should be used as the expiry time for the cached response
- (void)storeResponseForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;
// Removes cached data for a particular url
- (void)removeCachedDataForURL:(NSURL *)url;
// Should return an NSDictionary of cached headers for the passed URL, if it is stored in the cache
- (NSDictionary *)cachedResponseHeadersForURL:(NSURL *)url;
... ...
... ... @@ -80,10 +80,9 @@
zStream.next_in = bytes;
zStream.avail_in = (unsigned int)length;
zStream.avail_out = 0;
NSError *theError = nil;
NSInteger bytesProcessedAlready = zStream.total_out;
while (zStream.avail_in != 0) {
while (zStream.avail_out == 0) {
if (zStream.total_out-bytesProcessedAlready >= [outputData length]) {
[outputData increaseLengthBy:halfLength];
... ... @@ -103,13 +102,6 @@
}
}
if (theError) {
if (err) {
*err = theError;
}
return nil;
}
// Set real length
[outputData setLength: zStream.total_out-bytesProcessedAlready];
return outputData;
... ...
... ... @@ -77,7 +77,6 @@
zStream.next_in = bytes;
zStream.avail_in = (unsigned int)length;
zStream.avail_out = 0;
NSError *theError = nil;
NSInteger bytesProcessedAlready = zStream.total_out;
while (zStream.avail_in != 0) {
... ... @@ -101,13 +100,6 @@
}
}
if (theError) {
if (err) {
*err = theError;
}
return nil;
}
// Set real length
[outputData setLength: zStream.total_out-bytesProcessedAlready];
return outputData;
... ...
... ... @@ -35,11 +35,6 @@
// A helper function that determines if the server has requested data should not be cached by looking at the request's response headers
+ (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request;
// A date formatter that can be used to construct an RFC 1123 date
// The returned formatter is safe to use on the calling thread
// Do not use this formatter for parsing dates because the format can vary slightly - use ASIHTTPRequest's dateFromRFC1123String: class method instead
+ (NSDateFormatter *)rfc1123DateFormatter;
@property (assign, nonatomic) ASICachePolicy defaultCachePolicy;
@property (retain, nonatomic) NSString *storagePath;
@property (retain) NSRecursiveLock *accessLock;
... ...
This diff is collapsed. Click to expand it.
... ... @@ -2,7 +2,7 @@
// ASIHTTPRequest.h
//
// Created by Ben Copsey on 04/10/2007.
// Copyright 2007-2010 All-Seeing Interactive. All rights reserved.
// Copyright 2007-2011 All-Seeing Interactive. All rights reserved.
//
// A guide to the main features is available at:
// http://allseeing-i.com/ASIHTTPRequest
... ... @@ -92,7 +92,7 @@ typedef void (^ASIDataBlock)(NSData *data);
// Temporarily stores the url we are about to redirect to. Will be nil again when we do redirect
NSURL *redirectURL;
// The delegate, you need to manage setting and talking to your delegate in your subclasses
// The delegate - will be notified of various changes in state via the ASIHTTPRequestDelegate protocol
id <ASIHTTPRequestDelegate> delegate;
// Another delegate that is also notified of request status changes and progress updates
... ... @@ -100,7 +100,7 @@ typedef void (^ASIDataBlock)(NSData *data);
// NOTE: WILL BE RETAINED BY THE REQUEST
id <ASIHTTPRequestDelegate, ASIProgressDelegate> queue;
// HTTP method to use (GET / POST / PUT / DELETE / HEAD). Defaults to GET
// HTTP method to use (eg: GET / POST / PUT / DELETE / HEAD etc). Defaults to GET
NSString *requestMethod;
// Request body - only used when the whole body is stored in memory (shouldStreamPostDataFromDisk is false)
... ... @@ -192,6 +192,9 @@ typedef void (^ASIDataBlock)(NSData *data);
NSString *username;
NSString *password;
// User-Agent for this request
NSString *userAgent;
// Domain used for NTLM authentication
NSString *domain;
... ... @@ -343,8 +346,9 @@ typedef void (^ASIDataBlock)(NSData *data);
// Tells ASIHTTPRequest not to delete partial downloads, and allows it to use an existing file to resume a download. Defaults to NO.
BOOL allowResumeForFileDownloads;
// Custom user information associated with the request
// Custom user information associated with the request (not sent to the server)
NSDictionary *userInfo;
NSInteger tag;
// Use HTTP 1.0 rather than 1.1 (defaults to false)
BOOL useHTTPVersionOne;
... ... @@ -399,7 +403,10 @@ typedef void (^ASIDataBlock)(NSData *data);
// The number of times this request has retried (when numberOfTimesToRetryOnTimeout > 0)
int retryCount;
// Temporarily set to YES when a closed connection forces a retry (internally, this stops ASIHTTPRequest cleaning up a temporary post body)
BOOL willRetryRequest;
// When YES, requests will keep the connection to the server alive for a while to allow subsequent requests to re-use it for a substantial speed-boost
// Persistent connections will not be used if the server explicitly closes the connection
// Default is YES
... ... @@ -439,7 +446,6 @@ typedef void (^ASIDataBlock)(NSData *data);
// This timer checks up on the request every 0.25 seconds, and updates progress
NSTimer *statusTimer;
// The download cache that will be used for this request (use [ASIHTTPRequest setDefaultCache:cache] to configure a default cache
id <ASICacheDelegate> downloadCache;
... ... @@ -460,7 +466,6 @@ typedef void (^ASIDataBlock)(NSData *data);
BOOL shouldContinueWhenAppEntersBackground;
UIBackgroundTaskIdentifier backgroundTask;
#endif
// When downloading a gzipped response, the request will use this helper object to inflate the response
ASIDataDecompressor *dataDecompressor;
... ... @@ -794,6 +799,7 @@ typedef void (^ASIDataBlock)(NSData *data);
// Will be used as a user agent if requests do not specify a custom user agent
// Is only used when you have specified a Bundle Display Name (CFDisplayBundleName) or Bundle Name (CFBundleName) in your plist
+ (NSString *)defaultUserAgentString;
+ (void)setDefaultUserAgentString:(NSString *)agent;
#pragma mark mime-type detection
... ... @@ -890,6 +896,7 @@ typedef void (^ASIDataBlock)(NSData *data);
@property (retain) NSString *username;
@property (retain) NSString *password;
@property (retain) NSString *userAgent;
@property (retain) NSString *domain;
@property (retain) NSString *proxyUsername;
... ... @@ -932,7 +939,7 @@ typedef void (^ASIDataBlock)(NSData *data);
@property (retain,readonly) NSString *responseStatusMessage;
@property (retain) NSMutableData *rawResponseData;
@property (assign) NSTimeInterval timeOutSeconds;
@property (retain) NSString *requestMethod;
@property (retain, nonatomic) NSString *requestMethod;
@property (retain) NSMutableData *postBody;
@property (assign) unsigned long long contentLength;
@property (assign) unsigned long long postLength;
... ... @@ -947,6 +954,7 @@ typedef void (^ASIDataBlock)(NSData *data);
@property (assign) BOOL allowCompressedResponse;
@property (assign) BOOL allowResumeForFileDownloads;
@property (retain) NSDictionary *userInfo;
@property (assign) NSInteger tag;
@property (retain) NSString *postBodyFilePath;
@property (assign) BOOL shouldStreamPostDataFromDisk;
@property (assign) BOOL didCreateTemporaryPostDataFile;
... ...
This diff is collapsed. Click to expand it.
... ... @@ -30,3 +30,8 @@
#ifndef DEBUG_PERSISTENT_CONNECTIONS
#define DEBUG_PERSISTENT_CONNECTIONS 0
#endif
// When set to 1, ASIHTTPRequests will print information about HTTP authentication (Basic, Digest or NTLM) to the console
#ifndef DEBUG_HTTP_AUTHENTICATION
#define DEBUG_HTTP_AUTHENTICATION 0
#endif
... ...
... ... @@ -377,7 +377,7 @@ static NSMutableArray *requestsUsingXMLParser = nil;
// Strip the content encoding if the original response was gzipped
if ([self isResponseCompressed]) {
NSMutableDictionary *headers = [[self responseHeaders] mutableCopy];
NSMutableDictionary *headers = [[[self responseHeaders] mutableCopy] autorelease];
[headers removeObjectForKey:@"Content-Encoding"];
[self setResponseHeaders:headers];
}
... ...
... ... @@ -147,7 +147,33 @@
success = ([inflatedString isEqualToString:originalString]);
GHAssertTrue(success,@"deflate data is not the same as that generated by gzip");
// Test for bug https://github.com/pokeb/asi-http-request/issues/147
[ASIHTTPRequest removeFileAtPath:gzippedFilePath error:&error];
[ASIHTTPRequest removeFileAtPath:filePath error:&error];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://spaceharvest.com/i/screen6.png"]];
[request setDownloadDestinationPath:filePath];
[request startSynchronous];
if (![ASIDataCompressor compressDataFromFile:filePath toFile:gzippedFilePath error:&error]) {
GHFail(@"Deflate failed because %@",error);
}
unsigned long long originalFileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error] fileSize];
[ASIHTTPRequest removeFileAtPath:filePath error:&error];
task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:@"/usr/bin/gzip"];
[task setArguments:[NSArray arrayWithObjects:@"-d",gzippedFilePath,nil]];
[task launch];
[task waitUntilExit];
unsigned long long inflatedFileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error] fileSize];
success = (originalFileSize == inflatedFileSize);
GHAssertTrue(success,@"inflated data is not the same size as the original");
}
@end
... ...
... ... @@ -11,6 +11,7 @@
@interface ASIDownloadCacheTests : ASITestCase {
NSUInteger requestsFinishedCount;
BOOL requestRedirectedWasCalled;
}
@end
... ...
... ... @@ -14,6 +14,7 @@
@interface ASIDownloadCacheTests ()
- (void)runCacheOnlyCallsRequestFinishedOnceTest;
- (void)finishCached:(ASIHTTPRequest *)request;
- (void)runRedirectTest;
@end
... ... @@ -164,9 +165,32 @@
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Request says it used a cached response, but there wasn't one to use");
success = !![request error];
success = ([request error] != nil);
GHAssertTrue(success,@"Request had no error set");
// Cache some data
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"];
request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSString *path = [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request];
success = (path != nil);
GHAssertTrue(success,@"Cache failed to store data");
path = [[ASIDownloadCache sharedCache] pathToStoreCachedResponseHeadersForRequest:request];
success = (path != nil);
GHAssertTrue(success,@"Cache failed to store data");
// Make sure data gets removed
[[ASIDownloadCache sharedCache] removeCachedDataForURL:url];
path = [[ASIDownloadCache sharedCache] pathToCachedResponseDataForURL:url];
success = (path == nil);
GHAssertTrue(success,@"Cache failed to remove data");
path = [[ASIDownloadCache sharedCache] pathToCachedResponseHeadersForURL:url];
success = (path == nil);
GHAssertTrue(success,@"Cache failed to remove data");
// Test ASIDontLoadCachePolicy
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
... ... @@ -307,14 +331,16 @@
- (void)test304
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"];
// Test default cache policy
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"]];
request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
BOOL success = ([request responseStatusCode] == 200);
... ... @@ -325,6 +351,30 @@
success = ([[request responseData] length]);
GHAssertTrue(success,@"Response was empty");
// Test 304 updates expiry date
url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content_not_modified_but_expires_tomorrow"];
request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
NSTimeInterval expiryTimestamp = [[[[ASIDownloadCache sharedCache] cachedResponseHeadersForURL:url] objectForKey:@"X-ASIHTTPRequest-Expires"] doubleValue];
// Wait to give the expiry date a chance to change
sleep(2);
request = [ASIHTTPRequest requestWithURL:url];
[request setCachePolicy:ASIAskServerIfModifiedCachePolicy];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success, @"Cached data should have been used");
NSTimeInterval newExpiryTimestamp = [[[[ASIDownloadCache sharedCache] cachedResponseHeadersForURL:url] objectForKey:@"X-ASIHTTPRequest-Expires"] doubleValue];
NSLog(@"%@",[request responseString]);
success = (newExpiryTimestamp > expiryTimestamp);
GHAssertTrue(success, @"Failed to update expiry timestamp on 304");
}
- (void)testStringEncoding
... ... @@ -410,4 +460,50 @@
requestsFinishedCount++;
}
- (void)testRedirect
{
// Run this request on the main thread to force delegate calls to happen synchronously
[self performSelectorOnMainThread:@selector(runRedirectTest) withObject:nil waitUntilDone:YES];
}
- (void)runRedirectTest
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cached-redirect"]];
[request startSynchronous];
BOOL success = ([[[request url] absoluteString] isEqualToString:@"http://allseeing-i.com/i/logo.png"]);
GHAssertTrue(success,@"Request did not redirect correctly, cannot proceed with test");
requestRedirectedWasCalled = NO;
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cached-redirect"]];
[request setDelegate:self];
[request startSynchronous];
success = ([request didUseCachedResponse]);
GHAssertTrue(success,@"Failed to cache final response");
GHAssertTrue(requestRedirectedWasCalled,@"Failed to call requestRedirected");
}
- (void)requestRedirected:(ASIHTTPRequest *)redirected
{
requestRedirectedWasCalled = YES;
}
- (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL
{
BOOL success = ([[newURL absoluteString] isEqualToString:@"http://allseeing-i.com/i/logo.png"]);
GHAssertTrue(success,@"Request did not redirect correctly, cannot proceed with test");
success = ([request didUseCachedResponse]);
GHAssertTrue(success,@"Failed to cache redirect response");
[request redirectToURL:newURL];
}
@end
... ...
... ... @@ -20,6 +20,7 @@
}
- (void)testBasicDownload;
- (void)testBase64Encode;
- (void)testDelegateMethods;
- (void)testConditionalGET;
- (void)testException;
... ... @@ -56,7 +57,7 @@
#endif
- (void)testAutomaticRetry;
- (void)testCloseConnection;
- (void)testPersistentConnectionTimeout;
- (void)testPersistentConnections;
- (void)testNilPortCredentialsMatching;
@property (retain, nonatomic) NSMutableData *responseData;
... ...
This diff is collapsed. Click to expand it.
... ... @@ -15,6 +15,7 @@ Felis de Brito
Sam DeVore (http://scidsolutions.com)
Nathan de Vries (http://www.atnan.com)
Matthew Frederick
Ole Gammelgaard (http://www.trickclown.dk)
Ganasa LLC
James Hartzell
Hunter Hillegas
... ... @@ -29,9 +30,11 @@ John Paul May (http://smhk.com)
Rosario Milone (http://vgmtorrents.net)
Jirapong Nanta (http://bananacoding.com)
Ben Pettit (http://http://digimulti.com)
George Photakis
Spencer Pieters (http://www.appwizard.be)
Peter Pistorius (http://appfactory.co.za)
Shawn Roske
Collin Ruffenach
Alessandro Segala (http://letsdev.it)
Ben Scheirman
Basil Shkara (http://www.oiledmachine.com)
... ...
... ... @@ -70,14 +70,14 @@
[[UIApplication sharedApplication] cancelAllLocalNotifications];
// Create a new notification
UILocalNotification* alarm = [[[UILocalNotification alloc] init] autorelease];
if (alarm) {
[alarm setFireDate:[NSDate date]];
[alarm setTimeZone:[NSTimeZone defaultTimeZone]];
[alarm setRepeatInterval:0];
[alarm setSoundName:@"alarmsound.caf"];
[alarm setAlertBody:@"Boom!\r\n\r\nUpload is finished!"];
[[UIApplication sharedApplication] scheduleLocalNotification:alarm];
UILocalNotification *notification = [[[UILocalNotification alloc] init] autorelease];
if (notification) {
[notification setFireDate:[NSDate date]];
[notification setTimeZone:[NSTimeZone defaultTimeZone]];
[notification setRepeatInterval:0];
[notification setSoundName:@"alarmsound.caf"];
[notification setAlertBody:@"Boom!\r\n\r\nUpload is finished!"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
#endif
}
... ...