Ben Copsey

Added gzip for request bodies

Comments / code tweaks
... ... @@ -44,12 +44,15 @@ extern NSString* const NetworkRequestErrorDomain;
// A queue delegate that should *ALSO* be notified of delegate message (used by ASINetworkQueue)
id queue;
// HTTP method to use (GET / POST / PUT / DELETE). Defaults to GET
// HTTP method to use (GET / POST / PUT / DELETE / HEAD). Defaults to GET
NSString *requestMethod;
// Request body - only used when the whole body is stored in memory (shouldStreamPostDataFromDisk is false)
NSMutableData *postBody;
// gzipped request body used when shouldCompressRequestBody is YES
NSData *compressedPostBody;
// When true, post body will be streamed from a file on disk, rather than loaded into memory at once (useful for large uploads)
// Automatically set to true in ASIFormDataRequests when using setFile:forKey:
BOOL shouldStreamPostDataFromDisk;
... ... @@ -58,6 +61,9 @@ extern NSString* const NetworkRequestErrorDomain;
// You can set this yourself - useful if you want to PUT a file from local disk
NSString *postBodyFilePath;
// Path to a temporary file used to store a deflated post body (when shouldCompressPostBody is YES)
NSString *compressedPostBodyFilePath;
// Set to true when ASIHTTPRequest automatically created a temporary file containing the request body (when true, the file at postBodyFilePath will be deleted at the end of the request)
BOOL didCreateTemporaryPostDataFile;
... ... @@ -91,6 +97,10 @@ extern NSString* const NetworkRequestErrorDomain;
// If allowCompressedResponse is true, requests will inform the server they can accept compressed data, and will automatically decompress gzipped responses. Default is true.
BOOL allowCompressedResponse;
// If shouldCompressRequestBody is true, the request body will be gzipped. Default is false.
// You will probably need to enable this feature on your webserver to make this work. Tested with apache only.
BOOL shouldCompressRequestBody;
// When downloadDestinationPath is set, the result of this request will be downloaded to the file at this location
// If downloadDestinationPath is not set, download data will be stored in memory
NSString *downloadDestinationPath;
... ... @@ -203,11 +213,18 @@ extern NSString* const NetworkRequestErrorDomain;
// Prevents the body of the post being built more than once (largely for subclasses)
BOOL haveBuiltPostBody;
// Used internally, may reflect the size of the internal used by CFNetwork
// POST / PUT operations with body sizes greater than uploadBufferSize will not timeout unless more than uploadBufferSize bytes have been sent
// Likely to be 32KB on iPhone 3.0, 128KB on Mac OS X Leopard and iPhone 2.2.x
unsigned long long uploadBufferSize;
// Text encoding for responses that do not send a Content-Type with a charset value. Defaults to NSISOLatin1StringEncoding
NSStringEncoding defaultResponseEncoding;
// The text encoding of the response, will be defaultResponseEncoding if the server didn't specify. Can't be set.
NSStringEncoding responseEncoding;
// 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 assosiated with the request
... ... @@ -360,7 +377,7 @@ extern NSString* const NetworkRequestErrorDomain;
// Dump all session data (authentication and cookies)
+ (void)clearSession;
#pragma mark gzip compression
#pragma mark gzip decompression
// Uncompress gzipped data with zlib
+ (NSData *)uncompressZippedData:(NSData*)compressedData;
... ... @@ -369,6 +386,15 @@ extern NSString* const NetworkRequestErrorDomain;
+ (int)uncompressZippedDataFromFile:(NSString *)sourcePath toFile:(NSString *)destinationPath;
+ (int)uncompressZippedDataFromSource:(FILE *)source toDestination:(FILE *)dest;
#pragma mark gzip compression
// Compress data with gzip using zlib
+ (NSData *)compressData:(NSData*)uncompressedData;
// gzip compress data from a file, saving to another file, used for uploading when shouldCompressRequestBody is true
+ (int)compressDataFromFile:(NSString *)sourcePath toFile:(NSString *)destinationPath;
+ (int)compressDataFromSource:(FILE *)source toDestination:(FILE *)dest;
@property (retain) NSString *username;
@property (retain) NSString *password;
@property (retain) NSString *domain;
... ... @@ -417,4 +443,5 @@ extern NSString* const NetworkRequestErrorDomain;
@property (assign, readonly) unsigned long long partialDownloadSize;
@property (assign) BOOL shouldRedirect;
@property (assign) BOOL validatesSecureCertificate;
@property (assign) BOOL shouldCompressRequestBody;
@end
... ...
This diff is collapsed. Click to expand it.
... ... @@ -37,5 +37,6 @@
- (void)testTooMuchRedirection;
- (void)testRedirectToNewDomain;
- (void)test303Redirect;
- (void)testCompression;
@end
... ...
... ... @@ -10,7 +10,7 @@
#import "ASIHTTPRequest.h"
#import "ASINSStringAdditions.h"
#import "ASINetworkQueue.h"
#import "ASIFormDataRequest.h"
@implementation ASIHTTPRequestTests
... ... @@ -680,6 +680,58 @@
GHAssertTrue(success,@"Failed to use GET on new URL");
}
- (void)testCompression
{
NSString *content = @"This is the test content. This is the test content. This is the test content. This is the test content.";
// Test in memory compression / decompression
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
NSData *compressedData = [ASIHTTPRequest compressData:data];
NSData *uncompressedData = [ASIHTTPRequest uncompressZippedData:compressedData];
NSString *newContent = [[[NSString alloc] initWithBytes:[uncompressedData bytes] length:[uncompressedData length] encoding:NSUTF8StringEncoding] autorelease];
BOOL success = [newContent isEqualToString:content];
GHAssertTrue(success,@"Failed compress or decompress the correct data");
// Test file to file compression / decompression
NSString *basePath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
NSString *sourcePath = [basePath stringByAppendingPathComponent:@"text.txt"];
NSString *destPath = [basePath stringByAppendingPathComponent:@"text.txt.compressed"];
NSString *newPath = [basePath stringByAppendingPathComponent:@"text2.txt"];
[content writeToFile:sourcePath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
[ASIHTTPRequest compressDataFromFile:sourcePath toFile:destPath];
[ASIHTTPRequest uncompressZippedDataFromFile:destPath toFile:newPath];
success = [[NSString stringWithContentsOfFile:newPath encoding:NSUTF8StringEncoding error:NULL] isEqualToString:content];
GHAssertTrue(success,@"Failed compress or decompress the correct data");
// Test compressed body
// Body is deflated by ASIHTTPRequest, sent, inflated by the server, printed, deflated by mod_deflate, response is inflated by ASIHTTPRequest
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://asi/ASIHTTPRequest/tests/compressed_post_body"]];
[request setRequestMethod:@"PUT"];
[request setShouldCompressRequestBody:YES];
[request appendPostData:data];
[request start];
success = [[request responseString] isEqualToString:content];
GHAssertTrue(success,@"Failed to compress the body, or server failed to decompress it");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/compressed_post_body"]];
[request setRequestMethod:@"PUT"];
[request setShouldCompressRequestBody:YES];
[request setShouldStreamPostDataFromDisk:YES];
[request setUploadProgressDelegate:self];
[request setPostBodyFilePath:sourcePath];
[request start];
success = [[request responseString] isEqualToString:content];
GHAssertTrue(success,@"Failed to compress the body, or server failed to decompress it");
}
@end
... ...