Initial support for Gzip compression of HTTP Post Body

This commit is contained in:
Mattt Thompson 2011-08-05 15:13:22 -05:00
parent 884bacfd4b
commit c004ceb0f1
6 changed files with 7911 additions and 7349 deletions

View file

@ -0,0 +1,32 @@
// NSData+AFNetworking.h
//
// Copyright (c) 2011 Gowalla (http://gowalla.com/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
extern NSString * const kAFZlibErrorDomain;
@interface NSData (AFNetworking)
- (NSData *)dataByGZipCompressingWithError:(NSError **)error;
- (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error;
@end

View file

@ -0,0 +1,99 @@
// NSData+AFNetworking.m
//
// Copyright (c) 2011 Gowalla (http://gowalla.com/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "NSData+AFNetworking.h"
#import <zlib.h>
NSString * const kAFZlibErrorDomain = @"com.alamofire.zlib.error";
static inline NSUInteger NSDataEstimatedCompressedLength(NSData *data) {
return [data length] / 2;
}
typedef enum {
GzipDeflate = -1,
GzipInflate = 1,
} GzipOperation;
@interface NSData (_AFNetworking)
+ (NSData *)dataByTransformingData:(NSData *)data
usingGZipOperation:(GzipOperation)operation
error:(NSError **)error;
@end
@implementation NSData (_AFNetworking)
+ (NSData *)dataByTransformingData:(NSData *)data
usingGZipOperation:(GzipOperation)operation
error:(NSError **)error
{
z_stream zStream;
NSUInteger estimatedLength = NSDataEstimatedCompressedLength(data);
NSMutableData *mutableData = [NSMutableData dataWithLength:estimatedLength];
int status;
zStream.next_in = (Bytef *)[data bytes];
zStream.avail_in = (unsigned int)[data length];
zStream.avail_out = 0;
NSInteger bytesProcessedAlready = zStream.total_out;
while (zStream.avail_out == 0) {
if (zStream.total_out - bytesProcessedAlready >= [mutableData length]) {
[mutableData increaseLengthBy:estimatedLength / 2];
}
zStream.next_out = [mutableData mutableBytes] + zStream.total_out-bytesProcessedAlready;
zStream.avail_out = (unsigned int)([mutableData length] - (zStream.total_out-bytesProcessedAlready));
status = deflate(&zStream, Z_FINISH);
if (status == Z_STREAM_END) {
break;
} else if (status != Z_OK) {
if (error) {
*error = [NSError errorWithDomain:kAFZlibErrorDomain code:status userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Compression of data failed with code %hi", status] forKey:NSLocalizedDescriptionKey]];
}
return nil;
}
}
[mutableData setLength:zStream.total_out - bytesProcessedAlready];
return mutableData;
}
@end
#pragma mark -
@implementation NSData (AFNetworking)
- (NSData *)dataByGZipCompressingWithError:(NSError **)error {
return [NSData dataByTransformingData:self usingGZipOperation:GzipDeflate error:error];
}
- (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error {
return [NSData dataByTransformingData:self usingGZipOperation:GzipInflate error:error];
}
@end

View file

@ -27,6 +27,7 @@
- (void)setHTTPBodyWithData:(NSData *)data - (void)setHTTPBodyWithData:(NSData *)data
mimeType:(NSString *)mimeType mimeType:(NSString *)mimeType
forParameterNamed:(NSString *)parameterName forParameterNamed:(NSString *)parameterName
parameters:(NSDictionary *)parameters; parameters:(NSDictionary *)parameters
useCompression:(BOOL)useCompression;
@end @end

View file

@ -21,6 +21,7 @@
// THE SOFTWARE. // THE SOFTWARE.
#import "NSMutableURLRequest+AFNetworking.h" #import "NSMutableURLRequest+AFNetworking.h"
#import "NSData+AFNetworking.h"
@implementation NSMutableURLRequest (AFNetworking) @implementation NSMutableURLRequest (AFNetworking)
@ -28,6 +29,7 @@
mimeType:(NSString *)mimeType mimeType:(NSString *)mimeType
forParameterNamed:(NSString *)parameterName forParameterNamed:(NSString *)parameterName
parameters:(NSDictionary *)parameters parameters:(NSDictionary *)parameters
useCompression:(BOOL)useCompression
{ {
if ([[self HTTPMethod] isEqualToString:@"GET"]) { if ([[self HTTPMethod] isEqualToString:@"GET"]) {
[self setHTTPMethod:@"POST"]; [self setHTTPMethod:@"POST"];
@ -56,7 +58,19 @@
[mutableData appendData:data]; [mutableData appendData:data];
[mutableData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [mutableData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
if (useCompression) {
NSError *error = nil;
NSData *compressedData = [mutableData dataByGZipCompressingWithError:&error];
if (!error && compressedData) {
[self setHTTPBody:compressedData];
// Content-Encoding HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
[self setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
}
} else {
[self setHTTPBody:mutableData]; [self setHTTPBody:mutableData];
} }
}
@end @end

View file

@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
F85CE2D413EC478F00BFAE01 /* NSString+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2D313EC478F00BFAE01 /* NSString+AFNetworking.m */; }; F85CE2D413EC478F00BFAE01 /* NSString+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2D313EC478F00BFAE01 /* NSString+AFNetworking.m */; };
F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */; }; F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */; };
F85CE55513EC759200BFAE01 /* NSData+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE55413EC759200BFAE01 /* NSData+AFNetworking.m */; };
F85CE55B13EC771100BFAE01 /* libz.1.2.5.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F85CE55A13EC771100BFAE01 /* libz.1.2.5.dylib */; settings = {ATTRIBUTES = (Weak, ); }; };
F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */; }; F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */; };
F874B5DA13E0AA6500B28E3E /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CA13E0AA6500B28E3E /* AFImageCache.m */; }; F874B5DA13E0AA6500B28E3E /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CA13E0AA6500B28E3E /* AFImageCache.m */; };
F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; }; F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; };
@ -38,6 +40,9 @@
F85CE2D313EC478F00BFAE01 /* NSString+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+AFNetworking.m"; path = "../AFNetworking/NSString+AFNetworking.m"; sourceTree = "<group>"; }; F85CE2D313EC478F00BFAE01 /* NSString+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+AFNetworking.m"; path = "../AFNetworking/NSString+AFNetworking.m"; sourceTree = "<group>"; };
F85CE2DA13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableURLRequest+AFNetworking.h"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.h"; sourceTree = "<group>"; }; F85CE2DA13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableURLRequest+AFNetworking.h"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.h"; sourceTree = "<group>"; };
F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMutableURLRequest+AFNetworking.m"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.m"; sourceTree = "<group>"; }; F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMutableURLRequest+AFNetworking.m"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.m"; sourceTree = "<group>"; };
F85CE55313EC759100BFAE01 /* NSData+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+AFNetworking.h"; path = "../AFNetworking/NSData+AFNetworking.h"; sourceTree = "<group>"; };
F85CE55413EC759200BFAE01 /* NSData+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+AFNetworking.m"; path = "../AFNetworking/NSData+AFNetworking.m"; sourceTree = "<group>"; };
F85CE55A13EC771100BFAE01 /* libz.1.2.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.2.5.dylib; path = usr/lib/libz.1.2.5.dylib; sourceTree = SDKROOT; };
F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperation.m; path = ../AFNetworking/AFHTTPRequestOperation.m; sourceTree = "<group>"; }; F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperation.m; path = ../AFNetworking/AFHTTPRequestOperation.m; sourceTree = "<group>"; };
F874B5CA13E0AA6500B28E3E /* AFImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageCache.m; path = ../AFNetworking/AFImageCache.m; sourceTree = "<group>"; }; F874B5CA13E0AA6500B28E3E /* AFImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageCache.m; path = ../AFNetworking/AFImageCache.m; sourceTree = "<group>"; };
F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = "<group>"; }; F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = "<group>"; };
@ -88,6 +93,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
F85CE55B13EC771100BFAE01 /* libz.1.2.5.dylib in Frameworks */,
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */, F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */,
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */, F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */,
F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */, F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */,
@ -109,6 +115,8 @@
F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */, F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */,
F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */, F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */,
F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */, F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */,
F85CE55313EC759100BFAE01 /* NSData+AFNetworking.h */,
F85CE55413EC759200BFAE01 /* NSData+AFNetworking.m */,
); );
name = Categories; name = Categories;
sourceTree = "<group>"; sourceTree = "<group>";
@ -186,6 +194,7 @@
F8E469631395739D00DB05C8 /* Frameworks */ = { F8E469631395739D00DB05C8 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F85CE55A13EC771100BFAE01 /* libz.1.2.5.dylib */,
F8E469E413957E0400DB05C8 /* SystemConfiguration.framework */, F8E469E413957E0400DB05C8 /* SystemConfiguration.framework */,
F8E469E213957DF700DB05C8 /* SystemConfiguration.framework */, F8E469E213957DF700DB05C8 /* SystemConfiguration.framework */,
F8E469E013957DF100DB05C8 /* Security.framework */, F8E469E013957DF100DB05C8 /* Security.framework */,
@ -351,6 +360,7 @@
F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */, F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */,
F85CE2D413EC478F00BFAE01 /* NSString+AFNetworking.m in Sources */, F85CE2D413EC478F00BFAE01 /* NSString+AFNetworking.m in Sources */,
F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */, F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */,
F85CE55513EC759200BFAE01 /* NSData+AFNetworking.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };