Skip to content

Instantly share code, notes, and snippets.

@jidolstar
Created May 16, 2018 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jidolstar/00c2f5d03e26beec62b4f8e9a251d89c to your computer and use it in GitHub Desktop.
Save jidolstar/00c2f5d03e26beec62b4f8e9a251d89c to your computer and use it in GitHub Desktop.
Objective-C HTTP 통신
#import "bsHttpQueue.h"
#import "bsMacro.h"
#import "bsStr.h"
@interface bsHttpQueue(){
NSString *_url;
NSDictionary *_param;
NSString *_method;
NSUInteger _timeout;
}
@end
@implementation bsHttpQueue
+(bsHttpQueue*)GWithUrl:(NSString*)url method:(NSString*)method param:(NSDictionary*)param timeout:(NSUInteger)timeout end:(bsCallback*)end{
bsHttpQueue *queue = (bsHttpQueue*)[bsQueue GWithClassName:NSStringFromClass([self class]) end:end];
[queue __setWithUrl:url method:method param:param timeout:timeout];
return queue;
}
-(void)__setWithUrl:(NSString*)url method:(NSString*)method param:(NSDictionary*)param timeout:(NSUInteger)timeout {
_url = url;
_param = param;
_method = [[self class] __method:method];
_timeout = timeout;
}
-(void)startWithData:(id*)data error:(bsError **)error{
*data = [bsHttpQueue sendWithUrl:_url method:_method param:_param error:error timeout:_timeout];
}
+(NSMutableDictionary*)__headerFromParam:(NSDictionary*)param{ //key의 첫글자가 @이면 header로 본다.
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
if( param == nil || [param count] == 0 ) return dic;
[param enumerateKeysAndObjectsUsingBlock:^(NSString* key, id obj, BOOL *stop) {
if( key.length > 1 && [[key substringToIndex:1] isEqualToString:@"@"] ) {
key = [key substringFromIndex:1];
if( key.length == 0 ) return;
if( [obj isKindOfClass:[bsHttpFile class]] ) return; //@가 있더라도 파일이면 header가 될 수 없음!
if( [obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]] ) obj = [[bsStr sharedInstance] jsonDecode:obj];
else if( ![obj isKindOfClass:[NSString class]] ) obj = [[bsStr sharedInstance] str:obj];
[dic setObject:obj forKey:key];
}
}];
return dic;
}
+(NSMutableDictionary*)__dataFromParam:(NSDictionary*)param{ //key의 첫글자가 @가 아니면 data로 본다.
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
if( param == nil || [param count] == 0 ) return dic;
[param enumerateKeysAndObjectsUsingBlock:^(NSString* key, id obj, BOOL *stop) {
if( key.length > 0 && ![[key substringToIndex:1] isEqualToString:@"@"] ) {
if( [obj isKindOfClass:[bsHttpFile class]] ) return;
else if( [obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]] ) obj = [[bsStr sharedInstance] jsonDecode:obj];
else if( ![obj isKindOfClass:[NSString class]] ) obj = [[bsStr sharedInstance] str:obj];
[dic setObject:obj forKey:key];
}
}];
return dic;
}
+(NSMutableDictionary*)__fileFromParam:(NSDictionary*)param{
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
if( param == nil || [param count] == 0 ) return dic;
[param enumerateKeysAndObjectsUsingBlock:^(NSString* key, id obj, BOOL *stop) {
if( [[key substringToIndex:1] isEqualToString:@"@"] ) return; //key에 @가 첫글자이면 무시함!
if( key.length == 0 ) return;
if( [obj isKindOfClass:[bsHttpFile class]] && [(bsHttpFile*)obj count] > 0 ){
[dic setObject:obj forKey:key];
}
}];
return dic;
}
+(NSString*)__queryStringFromData:(NSDictionary*)data{
if( data == nil || [data count] == 0 ) return @"";
NSMutableString *str = [[NSMutableString alloc] init];
__block unsigned long i, j;
i = 0;
j = [data count];
[data enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL *stop) {
[str appendString:[[bsStr sharedInstance] urlEncode:key]];
[str appendString:@"="];
[str appendString:[[bsStr sharedInstance] urlEncode:value]];
if( i < j - 1 ) [str appendString:@"&"];
i++;
}];
return [NSString stringWithString:str];
}
+(NSString*)__method:(NSString*)method{
method = [method uppercaseString];
if( [method isEqualToString:HTTP_METHOD_GET] || [method isEqualToString:HTTP_METHOD_POST] || [method isEqualToString:HTTP_METHOD_PUT] || [method isEqualToString:HTTP_METHOD_DELETE] ){
return method;
}
bsException(@"http method는 GET, POST, PUT, DELETE중 하나이어야만 합니다.");
return nil;
}
+(NSData*)sendWithUrl:(NSString*)url method:(NSString*)method param:(NSDictionary*)param error:(bsError**)error timeout:(NSUInteger)timeout{
if( timeout < 5 ) timeout = 5;
else if( timeout > 60 ) timeout = 60;
method = [self __method:method];
@try {
NSDictionary *header = [self __headerFromParam:param];
NSDictionary *data = [self __dataFromParam:param];
NSDictionary *file = [self __fileFromParam:param];
NSString *book = nil;
*error = nil;
if ( [method isEqualToString:HTTP_METHOD_GET] ) {
NSMutableString *str = [[NSMutableString alloc] init];
if( [url rangeOfString:@"#"].length > 0 ) {
NSArray *urlMark = [[bsStr sharedInstance] split:url seperator:@"#" trim:YES];
url = urlMark[0];
book = urlMark[1];
}
[str appendString:url];
if( [url rangeOfString:@"?"].length > 0 ) [str appendString:@"&"];
else [str appendString:@"?"];
[str appendString:[self __queryStringFromData:data]];
if( book != nil ) {
[str appendString:@"#"];
[str appendString:book];
}
url = [NSString stringWithString:str];
data = nil;
}
if ( [method isEqualToString:HTTP_METHOD_GET] || [method isEqualToString:HTTP_METHOD_DELETE] ){ //(?)GET, DELETE 방식은 파일업로드 지원 안함
file = nil; //GET은 File을 보낼 수 없음
}
NSHTTPURLResponse *response = nil;
NSError *err = nil;
NSData *returnData;
NSMutableData *body = [NSMutableData data];
NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:timeout];
[request setHTTPMethod:method];
[request setValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"];
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; //gzip 받아줌
if( header && [header count] > 0 ){ //header셋팅
[header enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL *stop) {
[request setValue:value forHTTPHeaderField:key];
}];
}
if( file && [file count] > 0 ) { //file이 있다면 파일처리하자.
NSString *BOUNDARY = @"-----------------bs-----";
[request setValue:[NSString stringWithFormat:@"multipart/form-data, boundary=%@", BOUNDARY] forHTTPHeaderField:@"Content-Type"];
NSData *crlf =[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding];
NSData *boundary = [[NSString stringWithFormat:@"--%@", BOUNDARY] dataUsingEncoding:NSUTF8StringEncoding];
NSData *disp0 = [@"Content-Disposition: form-data; name=\"" dataUsingEncoding:NSUTF8StringEncoding];
NSData *disp1 = [@"\"; filename=\"" dataUsingEncoding:NSUTF8StringEncoding];
NSData *disp2 = [@"\"" dataUsingEncoding:NSUTF8StringEncoding];
NSData *octet = [@"Content-Type: application/octet-stream" dataUsingEncoding:NSUTF8StringEncoding];
if( data != nil ) {
[data enumerateKeysAndObjectsUsingBlock:^(NSString* key, id obj, BOOL *stop) {
[body appendData:boundary];
[body appendData:crlf];
[body appendData:disp0];
[body appendData:[key dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:disp2];
[body appendData:crlf];
[body appendData:crlf];
if( [obj isKindOfClass:[NSString class]] ) {
[body appendData:[obj dataUsingEncoding:NSUTF8StringEncoding]];
} else {
[body appendData:[[[bsStr sharedInstance] str:obj] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:crlf];
}];
}
[file enumerateKeysAndObjectsUsingBlock:^(NSString *key, bsHttpFile *f, BOOL *stop) {
[f loop:^(NSString *name, NSData *data) {
[body appendData:boundary];
[body appendData:crlf];
[body appendData:disp0];
[body appendData:[key dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:disp1];
[body appendData:[name dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:disp2];
[body appendData:crlf];
[body appendData:octet];
[body appendData:crlf];
[body appendData:crlf];
[body appendData:data];
[body appendData:crlf];
}];
[bsHttpFile PUT:f]; //pool로 돌려줌
}];
[body appendData:boundary];
[body appendData:[@"--" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:crlf];
[body appendData:crlf];
}else if( data && [data count] > 0 ){
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[body appendData:[[self __queryStringFromData:data] dataUsingEncoding:NSUTF8StringEncoding]];
}
[request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[body length]] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:body];
returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
if ( err == nil ) {
return returnData;
} else {
*error = [bsError POPWithMsg:[NSString stringWithFormat:@"%@", err] data:err.userInfo func:__FUNCTION__ line:__LINE__];
return nil;
}
}
@catch (NSException *e) {
*error = [bsError POPWithMsg:[NSString stringWithFormat:@"[%@]%@", [e name], [e reason]] data:[e userInfo] func:__FUNCTION__ line:__LINE__];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment