Skip to content

Commit

Permalink
Replacing NSMutableURLRequest category method with more flexible cons…
Browse files Browse the repository at this point in the history
…tructor in AFRestClient

Adding AFRestClient -multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock:

Defining AFMultipartFormDataProxy protocol

Replacing constant value for string encoding with @Property with default of NSUTF8Encoding
  • Loading branch information
mattt committed Sep 21, 2011
1 parent ca02e02 commit 8b86051
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 119 deletions.
24 changes: 20 additions & 4 deletions AFNetworking/AFRestClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#import <Foundation/Foundation.h>
#import "AFHTTPRequestOperation.h"

#import "NSMutableURLRequest+AFNetworking.h"
@protocol AFMultipartFormDataProxy;

@interface AFRestClient : NSObject {
@private
Expand Down Expand Up @@ -112,6 +112,12 @@
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
path:(NSString *)path parameters:(NSDictionary *)parameters;

- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
path:(NSString *)path
parameters:(NSDictionary *)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormDataProxy>formData))block;


///--------------------------------
/// @name Enqueuing HTTP Operations
///--------------------------------
Expand All @@ -132,9 +138,9 @@
///---------------------------
/// @name Making HTTP Requests
///---------------------------
- (void)getPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id response))success
- (void)getPath:(NSString *)path
parameters:(NSDictionary *)parameters
success:(void (^)(id response))success
failure:(void (^)(NSError *error))failure;

- (void)postPath:(NSString *)path
Expand All @@ -152,3 +158,13 @@
success:(void (^)(id response))success
failure:(void (^)(NSError *error))failure;
@end

#pragma mark -

@protocol AFMultipartFormDataProxy <NSObject>
- (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body;
- (void)appendPartWithFormData:(NSData *)data name:(NSString *)name;
- (void)appendPartWithFile:(NSURL *)fileURL fileName:(NSString *)fileNameOrNil;
- (void)appendData:(NSData *)data;
- (void)appendString:(NSString *)string;
@end
138 changes: 138 additions & 0 deletions AFNetworking/AFRestClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,31 @@
#import "AFRestClient.h"
#import "AFJSONRequestOperation.h"

static NSString * const kAFMultipartFormLineDelimiter = @"\r\n"; // CRLF
static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY";

static NSString * AFMultipartFormEncapsulationBoundary() {
return [NSString stringWithFormat:@"--%@", kAFMultipartFormBoundary];
}

static NSString * AFMultipartFormFinalBoundary() {
return [NSString stringWithFormat:@"--%@--", kAFMultipartFormBoundary];
}

@interface AFMutableMultipartFormData : NSObject <AFMultipartFormDataProxy> {
@private
NSStringEncoding _stringEncoding;
NSMutableArray *_lines;
}

- (id)initWithStringEncoding:(NSStringEncoding)encoding;

- (NSData *)data;

@end

#pragma mark -

static NSString * AFBase64EncodedStringFromString(NSString *string) {
NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string length]];
NSUInteger length = [data length];
Expand Down Expand Up @@ -161,6 +186,42 @@ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)p
return request;
}

- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
path:(NSString *)path
parameters:(NSDictionary *)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormDataProxy>formData))block
{
if (!([method isEqualToString:@"POST"] || [method isEqualToString:@"PUT"] || [method isEqualToString:@"DELETE"])) {
[NSException raise:@"Invalid HTTP Method" format:@"%@ is not supported for multipart form requests; must be either POST, PUT, or DELETE", method];
return nil;
}

NSMutableURLRequest *request = [self requestWithMethod:method path:path parameters:nil];
__block AFMutableMultipartFormData *formData = [[AFMutableMultipartFormData alloc] init];

id key = nil;
NSEnumerator *enumerator = [parameters keyEnumerator];
while ((key = [enumerator nextObject])) {
id value = [parameters valueForKey:key];
if (![value isKindOfClass:[NSData class]]) {
value = [value description];
}

[formData appendPartWithFormData:[value dataUsingEncoding:self.stringEncoding] name:[key description]];
}

if (block) {
block(formData);
}

[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:[formData data]];

[formData autorelease];

return request;
}

- (void)enqueueHTTPOperation:(AFHTTPRequestOperation *)operation {
[self.operationQueue addOperation:operation];
}
Expand Down Expand Up @@ -209,3 +270,80 @@ - (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters succes
}

@end

#pragma mark -

// multipart/form-data; see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2
@interface AFMutableMultipartFormData ()
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
@property (readwrite, nonatomic, retain) NSMutableArray *lines;

- (void)appendBlankLine;
@end

@implementation AFMutableMultipartFormData
@synthesize stringEncoding = _stringEncoding;
@synthesize lines = _lines;

- (id)initWithStringEncoding:(NSStringEncoding)encoding {
self = [super init];
if (!self) {
return nil;
}

self.stringEncoding = encoding;
self.lines = [NSMutableArray array];

return self;
}

- (void)dealloc {
[_lines release];
[super dealloc];
}

- (NSData *)data {
NSLog(@"DATA: %@", [[self.lines componentsJoinedByString:kAFMultipartFormLineDelimiter] stringByAppendingString:AFMultipartFormFinalBoundary()]);

return [[[[self.lines componentsJoinedByString:kAFMultipartFormLineDelimiter] stringByAppendingString:AFMultipartFormFinalBoundary()] stringByAppendingString:kAFMultipartFormLineDelimiter] dataUsingEncoding:self.stringEncoding];
}

#pragma mark - AFMultipartFormDataProxy

- (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body {
for (NSString *field in [headers allKeys]) {
[self appendString:[NSString stringWithFormat:@"%@: %@", field, [headers valueForKey:field]]];
}

[self appendBlankLine];
[self appendData:body];
}

- (void)appendPartWithFormData:(NSData *)data name:(NSString *)name {
[self appendPartWithHeaders:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"] body:data];
}

- (void)appendPartWithFile:(NSURL *)fileURL fileName:(NSString *)fileNameOrNil {
if (![fileURL isFileURL]) {
[NSException raise:@"Invalid fileURL value" format:@"%@ must be a valid file URL", fileURL];
return;
}

NSData *data = [NSData dataWithContentsOfFile:[fileURL absoluteString]];
NSString *fileName = fileNameOrNil ? fileNameOrNil : [[fileURL lastPathComponent] stringByAppendingPathExtension:[fileURL pathExtension]];
[self appendPartWithHeaders:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"file; filename=\"%@\"", fileName] forKey:@"Content-Disposition"] body:data];
}

- (void)appendData:(NSData *)data {
[self appendString:[[[NSString alloc] initWithData:data encoding:self.stringEncoding] autorelease]];
}

- (void)appendString:(NSString *)string {
[self.lines addObject:string];
}

- (void)appendBlankLine {
[self appendString:@""];
}

@end
33 changes: 0 additions & 33 deletions AFNetworking/NSMutableURLRequest+AFNetworking.h

This file was deleted.

76 changes: 0 additions & 76 deletions AFNetworking/NSMutableURLRequest+AFNetworking.m

This file was deleted.

6 changes: 0 additions & 6 deletions Example/AFNetworking Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
objects = {

/* Begin PBXBuildFile section */
F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */; };
F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */; };
F874B5DA13E0AA6500B28E3E /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CA13E0AA6500B28E3E /* AFImageCache.m */; };
F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; };
Expand All @@ -34,8 +33,6 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
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>"; };
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>"; };
F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -101,8 +98,6 @@
F85CE2D613EC47BC00BFAE01 /* Categories */ = {
isa = PBXGroup;
children = (
F85CE2DA13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.h */,
F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */,
F874B5D713E0AA6500B28E3E /* UIImage+AFNetworking.h */,
F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */,
F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */,
Expand Down Expand Up @@ -348,7 +343,6 @@
F874B5DE13E0AA6500B28E3E /* AFRestClient.m in Sources */,
F874B5DF13E0AA6500B28E3E /* UIImage+AFNetworking.m in Sources */,
F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */,
F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

0 comments on commit 8b86051

Please sign in to comment.