RequestHandler.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. //
  2. // RequestHandler.m
  3. // Giwa
  4. //
  5. // Created by Jason Lee on 12/16/14.
  6. // Copyright (c) jasondevelop. All rights reserved.
  7. //
  8. #import "JDObject.h"
  9. #import "AFHTTPRequestOperation.h"
  10. #import "JDJSONModel.h"
  11. #import "RequestHandler.h"
  12. #import "AFHTTPRequestOperationManager.h"
  13. #import "AFHTTPRequestOperationManager+Synchronous.h"
  14. #define NSEUCKREncoding -2147481280
  15. @interface RequestHandler () {
  16. NSString *_requestPath;
  17. }
  18. @end
  19. @implementation RequestHandler
  20. #pragma mark - URL Encoding
  21. - (NSString *)URLEncodedString:(NSString *)string
  22. {
  23. return [string stringByAddingPercentEscapesUsingEncoding:NSEUCKREncoding];
  24. // NSString *encodedString = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
  25. // (CFStringRef)string,
  26. // NULL,
  27. // (CFStringRef)@"!*'();:@&=+$,/?%#[]",
  28. // kCFStringEncodingUTF8);
  29. // return encodedString;
  30. }
  31. //- (NSString*)URLDecodedString:(NSString *)string
  32. //{
  33. //
  34. //
  35. //
  36. // NSString *result = (__bridge NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
  37. // (CFStringRef)string,
  38. // CFSTR(""),
  39. // kCFStringEncodingUTF8);
  40. // return result;
  41. //}
  42. #pragma mark - Prepare Request
  43. - (void)sendRequest {
  44. [[JDFacade facade] loadIndicator:YES allowUserInteraction:NO];
  45. }
  46. - (void)finishRequest {
  47. [[JDFacade facade] loadIndicator:NO allowUserInteraction:YES];
  48. }
  49. #pragma mark - URL Request
  50. - (void)sendAsyncRequestURLString:(NSString *)URLString method:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters completion:(RequestHandlerCompletionBlock)completion failure:(RequestHandlerFailureBlock)failure {
  51. [self sendRequest];
  52. NSString *encodURLString = [self URLEncodedString:[NSString stringWithFormat:@"%@%@", URLString, path]];
  53. NSLog(@"URL=%@", encodURLString);
  54. NSLog(@"PARAM=%@", parameters);
  55. NSError *error = nil;
  56. BOOL hasFile = NO, isDataImage = NO, isMultipartForm = parameters[ksHTTPMultipartForm] && [parameters[ksHTTPRequestPOST] boolValue] ? YES : NO;
  57. NSData *dataToUpload = nil;
  58. NSString *dataParameter = nil;
  59. NSInteger i = 0;
  60. for (NSObject *obj in parameters.allValues) {//파일형식이 있는지 체크,
  61. if (!hasFile && ([obj isKindOfClass:[UIImage class]] || [obj isKindOfClass:[NSData class]])) {
  62. isDataImage = [obj isKindOfClass:[UIImage class]];
  63. dataToUpload = isDataImage ? UIImageJPEGRepresentation((UIImage *)obj, 1.0) : (NSData *)obj;
  64. dataParameter = parameters.allKeys[i];
  65. hasFile = YES;
  66. break;
  67. }
  68. i++;
  69. }
  70. NSMutableURLRequest *request = nil;
  71. if (!hasFile && !isMultipartForm) {//no image
  72. request = [[AFHTTPRequestSerializer serializer] requestWithMethod:method URLString:encodURLString parameters:parameters error:&error];
  73. } else {//Multipart-form
  74. NSMutableDictionary *tmpParams = [NSMutableDictionary dictionaryWithDictionary:parameters];
  75. [tmpParams removeObjectForKey:dataParameter];
  76. request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:method URLString:encodURLString parameters:tmpParams constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
  77. NSString *fileName = isDataImage ? @"tmp.jpg" : @"tmp.txt";
  78. NSString *mimeType = isDataImage ? @"image/jpeg" : @"application/json"; //text/plain
  79. [formData appendPartWithFileData:dataToUpload name:dataParameter fileName:fileName mimeType:mimeType];
  80. } error:&error];
  81. }
  82. AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
  83. op.responseSerializer = [AFJSONResponseSerializer serializer];
  84. [[JDFacade facade] setCurrentOperation:op];
  85. [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
  86. [self finishRequest];
  87. NSLog(@"\n\nJSON=%@\n\n", responseObject);
  88. if (completion) {
  89. completion(responseObject);
  90. }
  91. } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  92. [self finishRequest];
  93. if (failure) {
  94. failure(error);
  95. }
  96. }];
  97. [[NSOperationQueue mainQueue] addOperation:op];
  98. }
  99. - (void)sendAsyncPostRequestURL:(NSString *)URLString path:(NSString *)path parameters:(NSDictionary *)parameters completion:(RequestHandlerCompletionBlock)completion failure:(RequestHandlerFailureBlock)failure {
  100. [self sendAsyncRequestURLString:URLString method:ksHTTPRequestPOST path:(NSString *)path parameters:parameters completion:completion failure:failure];
  101. }
  102. - (void)sendAsyncGetRequestURL:(NSString *)URLString path:(NSString *)path parameters:(NSDictionary *)parameters completion:(RequestHandlerCompletionBlock)completion failure:(RequestHandlerFailureBlock)failure {
  103. [self sendAsyncRequestURLString:URLString method:ksHTTPRequestGET path:(NSString *)path parameters:parameters completion:completion failure:failure];
  104. }
  105. #pragma mark - 비동기 API 요청
  106. - (void)sendAsyncGetRequestAPIPath:(NSString *)apiPath parameters:(NSDictionary *)parameters modelClass:(Class)modelClass completion:(RequestHandlerCompletionBlock)completion failure:(RequestHandlerFailureBlock)failure {
  107. [self sendAsyncRequestAPIPath:apiPath method:ksHTTPRequestGET parameters:parameters modelClass:modelClass showLoadingView:YES completion:completion failure:failure];
  108. }
  109. - (void)sendAsyncPostRequestAPIPath:(NSString *)apiPath parameters:(NSDictionary *)parameters modelClass:(Class)modelClass completion:(RequestHandlerCompletionBlock)completion failure:(RequestHandlerFailureBlock)failure {
  110. [self sendAsyncRequestAPIPath:apiPath method:ksHTTPRequestPOST parameters:parameters modelClass:modelClass showLoadingView:YES completion:completion failure:failure];
  111. }
  112. - (void)sendAsyncPostRequestAPIPath:(NSString *)apiPath parameters:(NSDictionary *)parameters modelClass:(Class)modelClass showLoadingView:(BOOL)showLoadingView completion:(RequestHandlerCompletionBlock)completion failure:(RequestHandlerFailureBlock)failure {
  113. [self sendAsyncRequestAPIPath:apiPath method:ksHTTPRequestPOST parameters:parameters modelClass:modelClass showLoadingView:showLoadingView completion:completion failure:failure];
  114. }
  115. - (void)sendAsyncRequestAPIPath:(NSString *)apiPath method:(NSString *)method parameters:(NSDictionary *)parameters modelClass:(Class)modelClass showLoadingView:(BOOL)showLoadingView completion:(RequestHandlerCompletionBlock)completion failure:(RequestHandlerFailureBlock)failure {
  116. _requestPath = apiPath;
  117. if (showLoadingView) {
  118. [self sendRequest];
  119. }
  120. NSString *rootPath = API_ROOT_PATH;
  121. NSString *pathURL = [self URLEncodedString:[NSString stringWithFormat:@"%@%@%@", kAPIServer, rootPath, apiPath]];
  122. NSLog(@"PATH=%@", pathURL);
  123. NSLog(@"PARAM=%@", parameters);
  124. NSError *error = nil;
  125. BOOL hasFile = NO, isDataImage = NO, isMultipartForm = parameters[ksHTTPMultipartForm] && [parameters[ksHTTPRequestPOST] boolValue] ? YES : NO;
  126. NSMutableArray *fileArray = nil;
  127. NSMutableArray *fileParams = nil;
  128. NSInteger index = 0;
  129. for (NSObject *obj in parameters.allValues) {//파일형식이 있는지 체크,
  130. if (([obj isKindOfClass:[UIImage class]] || [obj isKindOfClass:[NSData class]])) {
  131. if (!fileArray) {
  132. fileArray = [[NSMutableArray alloc] init];
  133. fileParams = [[NSMutableArray alloc] init];
  134. hasFile = YES;
  135. }
  136. isDataImage = [obj isKindOfClass:[UIImage class]];
  137. [fileArray addObject:isDataImage ? UIImageJPEGRepresentation((UIImage *)obj, 1.0) : (NSData *)obj];
  138. [fileParams addObject:parameters.allKeys[index]];
  139. }
  140. index++;
  141. }
  142. NSMutableURLRequest *request = nil;
  143. if (!hasFile && !isMultipartForm) {//no file
  144. request = [[AFJSONRequestSerializer serializer] requestWithMethod:method URLString:pathURL parameters:parameters error:&error];
  145. [request setHTTPMethod:method];
  146. [request setTimeoutInterval:kDefaultTimeOut];
  147. [request setValue:@"application/json;charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
  148. NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];
  149. //FIXME : when production
  150. #ifdef DEBUG_MODE
  151. language = @"ko";
  152. #endif
  153. [request setValue:language forHTTPHeaderField:@"Accept-Language"];
  154. } else {//Multipart-form
  155. NSMutableDictionary *tmpParams = [NSMutableDictionary dictionaryWithDictionary:parameters];
  156. [tmpParams removeObjectForKey:fileParams];
  157. request = [[AFJSONRequestSerializer serializer] multipartFormRequestWithMethod:method URLString:pathURL parameters:tmpParams constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
  158. NSString *mimeType = isDataImage ? @"image/jpeg" : @"text/plain";
  159. NSInteger i = 0;
  160. // NSString *name = [fileParams[i] substringToIndex:[fileParams[i] rangeOfString:@"_"].location];
  161. NSString *name = fileParams[i];
  162. for (NSData *dataToUpload in fileArray) {
  163. NSString *fileName = isDataImage ? [NSString stringWithFormat:@"tmp_%zd.jpg", i+1] : [NSString stringWithFormat:@"tmp_%zd.txt", i+1];
  164. [formData appendPartWithFileData:dataToUpload name:name fileName:fileName mimeType:mimeType];
  165. }
  166. } error:&error];
  167. }
  168. [request setValue:self.authorization ? self.authorization : ksEmptyString forHTTPHeaderField:@"Authorization"];
  169. [request setValue:self.homegrpId ? self.homegrpId : ksEmptyString forHTTPHeaderField:@"X-kneet-homegrp"];
  170. AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
  171. op.responseSerializer = [AFHTTPResponseSerializer serializer];
  172. [JDFacade facade].currentOperation = op;
  173. [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
  174. [self finishRequest];
  175. NSString *JSONString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
  176. #ifndef PRODUCT_MODE
  177. NSLog(@"\n\nJSON=%@\n\n", JSONString);
  178. #endif
  179. NSError *error = nil;
  180. id rawJSON = [NSJSONSerialization JSONObjectWithData:responseObject
  181. options:NSJSONReadingAllowFragments
  182. error:&error];
  183. id JSONModel = nil;
  184. if (modelClass) {
  185. if ([rawJSON isKindOfClass:[NSArray class]]) {
  186. NSDictionary *JSONDic = @{@"list": rawJSON};
  187. JSONModel = [[modelClass alloc] initWithDictionary:JSONDic error:&error];
  188. } else {
  189. JSONModel = [[modelClass alloc] initWithString:JSONString error:&error];
  190. }
  191. } else {
  192. JSONModel = rawJSON;
  193. }
  194. if (error) {//오류 처리
  195. // JSONModel *result = [[JSONModel alloc] initWithString:JSONString error:nil];
  196. //
  197. // NSString *resultMsg = result.resultMsg ? result.resultMsg : MSG_ALERT_API_FAIL;
  198. // [[GWFacade facade] alert:resultMsg];
  199. JSONModel = nil;
  200. }
  201. //쿠키 설정
  202. NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[operation.response allHeaderFields] forURL:operation.request.URL];
  203. if (cookies && cookies.count > 0) {
  204. [self setCookies:cookies];
  205. }
  206. if (completion) {
  207. completion(JSONModel);
  208. }
  209. } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  210. [self finishRequest];
  211. NSLog(@"HTTPStatus=%zd\n%@", operation.response.statusCode, error.localizedDescription);
  212. NSString *JSONString = [[NSString alloc] initWithData:operation.responseData encoding:NSUTF8StringEncoding];
  213. #ifndef PRODUCT_MODE
  214. NSLog(@"\n\nERROR=%@\n\n", JSONString);
  215. #endif
  216. JDErrorModel *jerror = [[JDErrorModel alloc] initWithString:JSONString error:&error];
  217. BOOL isLoginView = [[JDFacade facade].currentViewController isKindOfClass:[NSClassFromString(@"LoginViewController") class]];
  218. if (!isLoginView && [jerror.errorCode isEqualToString:API_RESPONSE_UNAUTHORIZED_TOKEN]) {//인증토큰이 만료된 경우, 로그인 이동
  219. [[JDFacade facade] gotoLoginViewWithExpiring];
  220. } else if (failure && jerror) {
  221. failure(jerror ? jerror : error);
  222. } else {
  223. [[JDFacade facade] retryAlert:MSG_ALERT_SERVER_FAIL completionHander:^{
  224. [self sendAsyncRequestAPIPath:apiPath method:method parameters:parameters modelClass:modelClass
  225. showLoadingView:showLoadingView completion:completion failure:failure];
  226. }];
  227. }
  228. }];
  229. [[NSOperationQueue mainQueue] addOperation:op];
  230. }
  231. #pragma mark - 동기 API 요청
  232. - (id)sendSyncRequestAPIPath:(NSString *)apiPath method:(NSString *)method parameters:(NSDictionary *)parameters modelClass:(Class)modelClass showLoadingView:(BOOL)showLoadingView {
  233. if (showLoadingView) {
  234. [self sendRequest];
  235. }
  236. NSString *rootPath = API_ROOT_PATH;
  237. NSString *pathURL = [self URLEncodedString:[NSString stringWithFormat:@"%@%@%@", kAPIServer, rootPath, apiPath]];
  238. NSLog(@"PATH=%@", pathURL);
  239. NSLog(@"PARAM=%@", parameters);
  240. NSError *error = nil;
  241. NSMutableURLRequest *request = [[AFJSONRequestSerializer serializer] requestWithMethod:method URLString:pathURL parameters:parameters error:&error];
  242. [request setHTTPMethod:method];
  243. [request setTimeoutInterval:kDefaultTimeOut];
  244. [request setValue:@"application/json;charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
  245. [request setValue:@"en" forHTTPHeaderField:@"Accept-Language"];
  246. [request setValue:self.authorization ? self.authorization : ksEmptyString forHTTPHeaderField:@"Authorization"];
  247. [request setValue:self.homegrpId ? self.homegrpId : ksEmptyString forHTTPHeaderField:@"X-kneet-homegrp"];
  248. AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
  249. op.responseSerializer = [AFHTTPResponseSerializer serializer];
  250. [op start];
  251. [op waitUntilFinished];
  252. // Must call responseObject before checking the error
  253. id responseObject = [op responseObject];
  254. if (showLoadingView) {
  255. [self finishRequest];
  256. }
  257. if (error) {
  258. return nil;
  259. }
  260. NSString *JSONString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
  261. #ifdef DEBUG
  262. NSLog(@"\n\nJSON=%@\n\n", JSONString);
  263. #endif
  264. id rawJSON = [NSJSONSerialization JSONObjectWithData:responseObject
  265. options:NSJSONReadingAllowFragments
  266. error:&error];
  267. id JSONModel = nil;
  268. if (modelClass) {
  269. if ([rawJSON isKindOfClass:[NSArray class]]) {
  270. NSDictionary *JSONDic = @{@"list": rawJSON};
  271. JSONModel = [[modelClass alloc] initWithDictionary:JSONDic error:&error];
  272. } else {
  273. JSONModel = [[modelClass alloc] initWithString:JSONString error:&error];
  274. }
  275. } else {
  276. JSONModel = rawJSON;
  277. }
  278. return JSONModel;
  279. }
  280. - (id)sendSyncPostRequestAPIPath:(NSString *)apiPath parameters:(NSDictionary *)parameters modelClass:(Class)modelClass showLoadingView:(BOOL)showLoadingView {
  281. return [self sendSyncRequestAPIPath:apiPath method:ksHTTPRequestPOST parameters:parameters modelClass:modelClass showLoadingView:showLoadingView];
  282. }
  283. - (id)sendSyncGetRequestAPIPath:(NSString *)apiPath parameters:(NSDictionary *)parameters modelClass:(Class)modelClass showLoadingView:(BOOL)showLoadinView {
  284. return [self sendSyncRequestAPIPath:apiPath method:ksHTTPRequestGET parameters:parameters modelClass:modelClass showLoadingView:showLoadinView];
  285. }
  286. #pragma mark - Cookies
  287. - (void)setCookies:(NSArray *)cookies {
  288. NSMutableDictionary* cookieDict = [NSMutableDictionary new];
  289. for(NSHTTPCookie* cookie in cookies){
  290. [cookieDict setValue:cookie.properties forKey:cookie.name];
  291. }
  292. //쿠키 설정
  293. NSHTTPCookie *localCookie = [NSHTTPCookie cookieWithProperties:cookieDict];
  294. [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:localCookie];
  295. }
  296. #pragma mark - Singleton
  297. + (RequestHandler *)handler {
  298. static RequestHandler *sharedRequestHandler = nil;
  299. static dispatch_once_t onceToken;
  300. dispatch_once(&onceToken, ^{
  301. sharedRequestHandler = [[self alloc] init];
  302. });
  303. return sharedRequestHandler;
  304. }
  305. - (id)init {
  306. if (self = [super init]) {
  307. }
  308. return self;
  309. }
  310. @end