Created
January 22, 2014 22:41
-
-
Save eoghain/8568881 to your computer and use it in GitHub Desktop.
NSMutableURLRequest category for sending multipart/mixed (i.e.batch) request to servers that can handle them (i.e. Google Cloud Storage, .NET Web API, UCWA, OData). To use, just create your request to the batch endpoint and add your batched requests to it using the addPart: method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSMutableURLRequest+MultipartBatch.h | |
// | |
// Created by Rob Booth on 1/17/14. | |
// | |
#import <Foundation/Foundation.h> | |
@interface NSMutableURLRequest (MultipartBatch) | |
- (NSString *)multipartRequestBody; | |
- (void)addPart:(NSURLRequest *)request; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSMutableURLRequest+MultipartBatch.m | |
// | |
// Created by Rob Booth on 1/17/14. | |
// | |
#import "NSMutableURLRequest+MultipartBatch.h" | |
static NSString * prefix = @"X-MultipartBatch-"; | |
@implementation NSMutableURLRequest (MultipartBatch) | |
- (NSString *)boundary | |
{ | |
if ([[self.allHTTPHeaderFields allKeys] containsObject:@"Content-Type"] == NO) | |
return nil; | |
NSString * contentType = (NSString *)[self.allHTTPHeaderFields objectForKey:@"Content-Type"]; | |
NSArray * contentTypeArray = [contentType componentsSeparatedByString:@"boundary="]; | |
if (contentTypeArray.count != 2) | |
return nil; | |
NSString * boundary = contentTypeArray[1]; | |
return [boundary stringByReplacingOccurrencesOfString:@"\"" withString:@""]; | |
} | |
- (void)addPart:(NSURLRequest *)request | |
{ | |
NSString * boundary = self.boundary; | |
NSString * mimeType = @"multipart/mixed"; | |
NSString * contentType = @"application/http; msgtype=request"; | |
if (boundary == nil) | |
{ | |
CFUUIDRef uuid = CFUUIDCreate(nil); | |
boundary = CFBridgingRelease(CFUUIDCreateString(nil, uuid)); | |
boundary = boundary.lowercaseString; | |
CFRelease(uuid); | |
[self addValue:[NSString stringWithFormat:@"%@; type=\"%@\"; boundary=\"%@\"", mimeType, contentType, boundary] forHTTPHeaderField:@"Content-Type"]; | |
} | |
NSMutableURLRequest * mutableRequest = [request mutableCopy]; | |
[mutableRequest addValue:contentType forHTTPHeaderField:[prefix stringByAppendingString:@"Content-Type"]]; | |
[mutableRequest addValue:[NSString stringWithFormat:@"<%p>", mutableRequest] forHTTPHeaderField:[prefix stringByAppendingString:@"Content-ID"]]; | |
NSString * finalBoundary = [NSString stringWithFormat:@"--%@--\r\n", boundary]; | |
NSString * body = [[NSString alloc] initWithData:self.HTTPBody encoding:NSUTF8StringEncoding]; | |
// Strip final boundary | |
body = [body stringByReplacingOccurrencesOfString:finalBoundary withString:@""]; | |
body = [body stringByAppendingString:[NSString stringWithFormat:@"--%@\r\n%@", boundary, mutableRequest.multipartRequestBody]]; | |
// Add final boundary | |
body = [body stringByAppendingString:finalBoundary]; | |
self.HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding]; | |
} | |
- (NSString *)multipartRequestBody | |
{ | |
NSString * multipartHeader = @""; | |
NSString * requestHeaders = @""; | |
NSString * requestBody = [[NSString alloc] initWithData:self.HTTPBody encoding:NSUTF8StringEncoding]; | |
for (NSString * key in [self.allHTTPHeaderFields allKeys]) | |
{ | |
if ([key hasPrefix:prefix]) | |
{ | |
multipartHeader = [multipartHeader stringByAppendingString:[NSString stringWithFormat:@"%@: %@\r\n", [key stringByReplacingOccurrencesOfString:prefix withString:@""], [self.allHTTPHeaderFields objectForKey:key]]]; | |
continue; | |
} | |
requestHeaders = [requestHeaders stringByAppendingString:[NSString stringWithFormat:@"%@: %@\r\n", key, [self.allHTTPHeaderFields objectForKey:key]]]; | |
} | |
NSString * queryString = @""; | |
if (self.URL.query.length > 0) | |
queryString = [NSString stringWithFormat:@"?%@", self.URL.query]; | |
/* | |
multipartHeader | |
method path(?queryString) HTTP/1.1 | |
Host: hostname | |
headers | |
body | |
*/ | |
return [NSString stringWithFormat:@"%@\r\n%@ %@%@ HTTP/1.1\r\nHost: %@\r\n%@\r\n%@\r\n", multipartHeader, self.HTTPMethod, self.URL.path, queryString, self.URL.host, requestHeaders, requestBody]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Lifesaver... can this be used under MIT or Apache2 terms?