RequestHandler.m 19 KB

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