No Description

OSSNetworking.m 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. //
  2. // OSSNetworking.m
  3. // oss_ios_sdk
  4. //
  5. // Created by zhouzhuo on 8/16/15.
  6. // Copyright (c) 2015 aliyun.com. All rights reserved.
  7. //
  8. #import "OSSDefine.h"
  9. #import "OSSNetworking.h"
  10. #import "OSSBolts.h"
  11. #import "OSSModel.h"
  12. #import "OSSUtil.h"
  13. #import "OSSLog.h"
  14. #import "OSSXMLDictionary.h"
  15. #import "NSMutableData+OSS_CRC.h"
  16. #import "OSSInputStreamHelper.h"
  17. #import "OSSNetworkingRequestDelegate.h"
  18. #import "OSSURLRequestRetryHandler.h"
  19. #import "OSSHttpResponseParser.h"
  20. @implementation OSSNetworkingConfiguration
  21. @end
  22. @implementation OSSNetworking
  23. - (instancetype)initWithConfiguration:(OSSNetworkingConfiguration *)configuration {
  24. if (self = [super init]) {
  25. self.configuration = configuration;
  26. NSOperationQueue * operationQueue = [NSOperationQueue new];
  27. NSURLSessionConfiguration * dataSessionConfig = nil;
  28. NSURLSessionConfiguration * uploadSessionConfig = nil;
  29. if (configuration.enableBackgroundTransmitService) {
  30. uploadSessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:self.configuration.backgroundSessionIdentifier];
  31. } else {
  32. uploadSessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
  33. }
  34. dataSessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
  35. if (configuration.timeoutIntervalForRequest > 0) {
  36. uploadSessionConfig.timeoutIntervalForRequest = configuration.timeoutIntervalForRequest;
  37. dataSessionConfig.timeoutIntervalForRequest = configuration.timeoutIntervalForRequest;
  38. }
  39. if (configuration.timeoutIntervalForResource > 0) {
  40. uploadSessionConfig.timeoutIntervalForResource = configuration.timeoutIntervalForResource;
  41. dataSessionConfig.timeoutIntervalForResource = configuration.timeoutIntervalForResource;
  42. }
  43. dataSessionConfig.URLCache = nil;
  44. uploadSessionConfig.URLCache = nil;
  45. if (configuration.proxyHost && configuration.proxyPort) {
  46. // Create an NSURLSessionConfiguration that uses the proxy
  47. NSDictionary *proxyDict = @{
  48. @"HTTPEnable" : [NSNumber numberWithInt:1],
  49. (NSString *)kCFStreamPropertyHTTPProxyHost : configuration.proxyHost,
  50. (NSString *)kCFStreamPropertyHTTPProxyPort : configuration.proxyPort,
  51. @"HTTPSEnable" : [NSNumber numberWithInt:1],
  52. (NSString *)kCFStreamPropertyHTTPSProxyHost : configuration.proxyHost,
  53. (NSString *)kCFStreamPropertyHTTPSProxyPort : configuration.proxyPort,
  54. };
  55. dataSessionConfig.connectionProxyDictionary = proxyDict;
  56. uploadSessionConfig.connectionProxyDictionary = proxyDict;
  57. }
  58. _dataSession = [NSURLSession sessionWithConfiguration:dataSessionConfig
  59. delegate:self
  60. delegateQueue:operationQueue];
  61. _uploadFileSession = [NSURLSession sessionWithConfiguration:uploadSessionConfig
  62. delegate:self
  63. delegateQueue:operationQueue];
  64. self.isUsingBackgroundSession = configuration.enableBackgroundTransmitService;
  65. _sessionDelagateManager = [OSSSyncMutableDictionary new];
  66. NSOperationQueue * queue = [NSOperationQueue new];
  67. if (configuration.maxConcurrentRequestCount) {
  68. queue.maxConcurrentOperationCount = configuration.maxConcurrentRequestCount;
  69. }
  70. self.taskExecutor = [OSSExecutor executorWithOperationQueue:queue];
  71. }
  72. return self;
  73. }
  74. - (OSSTask *)sendRequest:(OSSNetworkingRequestDelegate *)request {
  75. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
  76. OSSLogVerbose(@"NetWorkConnectedMsg : %@",[OSSUtil buildNetWorkConnectedMsg]);
  77. NSString *operator = [OSSUtil buildOperatorMsg];
  78. if(operator) OSSLogVerbose(@"Operator : %@",[OSSUtil buildOperatorMsg]);
  79. });
  80. OSSLogVerbose(@"send request --------");
  81. if (self.configuration.proxyHost && self.configuration.proxyPort) {
  82. request.isAccessViaProxy = YES;
  83. }
  84. /* set maximum retry */
  85. request.retryHandler.maxRetryCount = self.configuration.maxRetryCount;
  86. OSSTaskCompletionSource * taskCompletionSource = [OSSTaskCompletionSource taskCompletionSource];
  87. __weak OSSNetworkingRequestDelegate *weakRequest= request;
  88. request.completionHandler = ^(id responseObject, NSError * error) {
  89. [weakRequest reset];
  90. // 1.判断是否出错,如果出错的话,直接设置错误信息
  91. if (error)
  92. {
  93. [taskCompletionSource setError:error];
  94. }else
  95. {
  96. [self checkForCrc64WithResult:responseObject
  97. requestDelegate:weakRequest
  98. taskCompletionSource:taskCompletionSource];
  99. }
  100. };
  101. [self dataTaskWithDelegate:request];
  102. return taskCompletionSource.task;
  103. }
  104. - (void)checkForCrc64WithResult:(nonnull id)response requestDelegate:(OSSNetworkingRequestDelegate *)delegate taskCompletionSource:(OSSTaskCompletionSource *)source
  105. {
  106. OSSResult *result = (OSSResult *)response;
  107. BOOL hasRange = [delegate.internalRequest valueForHTTPHeaderField:@"Range"] != nil;
  108. NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:delegate.internalRequest.URL resolvingAgainstBaseURL:YES];
  109. BOOL hasXOSSProcess = [urlComponents.query containsString:@"x-oss-process"];
  110. BOOL enableCRC = delegate.crc64Verifiable;
  111. // 3.判断如果未开启crc校验,或者headerFields里面有Range字段或者参数表中存在
  112. // x-oss-process字段,都将不进行crc校验
  113. if (!enableCRC || hasRange || hasXOSSProcess)
  114. {
  115. [source setResult:response];
  116. }
  117. else
  118. {
  119. OSSLogVerbose(@"--- checkForCrc64WithResult --- ");
  120. // 如果服务端未返回crc信息,默认是成功的
  121. OSSLogVerbose(@"result.remoteCRC64ecma : %@",result.remoteCRC64ecma);
  122. OSSLogVerbose(@"if result.localCRC64ecma : %@",result.localCRC64ecma);
  123. if (!result.remoteCRC64ecma.oss_isNotEmpty)
  124. {
  125. [source setResult:response];
  126. return;
  127. }
  128. // getObject 操作的crc数值会在delegate.responseParser consumeHttpResponseBody 进行计算。
  129. // upload & put 操作在上传成功后再计算。
  130. // 如果用户设置onReceiveData block。无法计算localCRC64ecma
  131. if (!result.localCRC64ecma.oss_isNotEmpty)
  132. {
  133. OSSLogVerbose(@"delegate.uploadingFileURL : %@",delegate.uploadingFileURL);
  134. if (delegate.uploadingFileURL)
  135. {
  136. OSSInputStreamHelper *helper = [[OSSInputStreamHelper alloc] initWithURL:delegate.uploadingFileURL];
  137. [helper syncReadBuffers];
  138. if (helper.crc64 != 0) {
  139. result.localCRC64ecma = [NSString stringWithFormat:@"%llu",helper.crc64];
  140. }
  141. }
  142. else
  143. {
  144. result.localCRC64ecma = delegate.contentCRC;
  145. }
  146. OSSLogVerbose(@"finally result.localCRC64ecma : %@",result.localCRC64ecma);
  147. }
  148. // 针对append接口,需要多次计算crc值
  149. if ([delegate.lastCRC oss_isNotEmpty] && [result.localCRC64ecma oss_isNotEmpty])
  150. {
  151. uint64_t last_crc64,local_crc64;
  152. NSScanner *scanner = [NSScanner scannerWithString:delegate.lastCRC];
  153. [scanner scanUnsignedLongLong:&last_crc64];
  154. scanner = [NSScanner scannerWithString:result.localCRC64ecma];
  155. [scanner scanUnsignedLongLong:&local_crc64];
  156. NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:delegate.internalRequest.URL resolvingAgainstBaseURL:YES];
  157. NSArray<NSString *> *params = [urlComponents.query componentsSeparatedByString:@"&"];
  158. __block NSString *positionValue;
  159. [params enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
  160. if ([obj rangeOfString:@"position="].location == 0)
  161. {
  162. *stop = YES;
  163. positionValue = [obj substringFromIndex:9];
  164. }
  165. }];
  166. uint64_t position = [positionValue longLongValue];
  167. NSString *next_append_position = [result.httpResponseHeaderFields objectForKey:@"x-oss-next-append-position"];
  168. uint64_t length = [next_append_position longLongValue] - position;
  169. uint64_t crc_local = [OSSUtil crc64ForCombineCRC1:last_crc64 CRC2:local_crc64 length:(size_t)length];
  170. result.localCRC64ecma = [NSString stringWithFormat:@"%llu",crc_local];
  171. OSSLogVerbose(@"crc_local: %llu, crc_remote: %@,last_position: %llu,nextAppendPosition: %llu,length: %llu",crc_local,result.remoteCRC64ecma,position,[next_append_position longLongValue],length);
  172. }
  173. //如果服务器和本机计算的crc值不一致,则报crc校验失败;否则,认为上传任务执行成功
  174. if (result.remoteCRC64ecma.oss_isNotEmpty && result.localCRC64ecma.oss_isNotEmpty)
  175. {
  176. if ([result.remoteCRC64ecma isEqualToString:result.localCRC64ecma])
  177. {
  178. [source setResult:response];
  179. }else
  180. {
  181. NSString *errorMessage = [NSString stringWithFormat:@"crc validation fails(local_crc64ecma: %@,remote_crc64ecma: %@)",result.localCRC64ecma,result.remoteCRC64ecma];
  182. NSError *crcError = [NSError errorWithDomain:OSSClientErrorDomain
  183. code:OSSClientErrorCodeInvalidCRC
  184. userInfo:@{OSSErrorMessageTOKEN:errorMessage}];
  185. [source setError:crcError];
  186. }
  187. }
  188. else
  189. {
  190. [source setResult:response];
  191. }
  192. }
  193. }
  194. - (void)dataTaskWithDelegate:(OSSNetworkingRequestDelegate *)requestDelegate {
  195. [[[[[OSSTask taskWithResult:nil] continueWithExecutor:self.taskExecutor withSuccessBlock:^id(OSSTask *task) {
  196. OSSLogVerbose(@"start to intercept request");
  197. for (id<OSSRequestInterceptor> interceptor in requestDelegate.interceptors) {
  198. task = [interceptor interceptRequestMessage:requestDelegate.allNeededMessage];
  199. if (task.error) {
  200. return task;
  201. }
  202. }
  203. return task;
  204. }] continueWithSuccessBlock:^id(OSSTask *task) {
  205. return [requestDelegate buildInternalHttpRequest];
  206. }] continueWithSuccessBlock:^id(OSSTask *task) {
  207. NSURLSessionDataTask * sessionTask = nil;
  208. if (self.configuration.timeoutIntervalForRequest > 0) {
  209. requestDelegate.internalRequest.timeoutInterval = self.configuration.timeoutIntervalForRequest;
  210. }
  211. if (requestDelegate.uploadingData) {
  212. [requestDelegate.internalRequest setHTTPBody:requestDelegate.uploadingData];
  213. sessionTask = [_dataSession dataTaskWithRequest:requestDelegate.internalRequest];
  214. } else if (requestDelegate.uploadingFileURL) {
  215. sessionTask = [_uploadFileSession uploadTaskWithRequest:requestDelegate.internalRequest fromFile:requestDelegate.uploadingFileURL];
  216. if (self.isUsingBackgroundSession) {
  217. requestDelegate.isBackgroundUploadFileTask = YES;
  218. }
  219. } else { // not upload request
  220. sessionTask = [_dataSession dataTaskWithRequest:requestDelegate.internalRequest];
  221. }
  222. requestDelegate.currentSessionTask = sessionTask;
  223. requestDelegate.httpRequestNotSuccessResponseBody = [NSMutableData new];
  224. [self.sessionDelagateManager setObject:requestDelegate forKey:@(sessionTask.taskIdentifier)];
  225. if (requestDelegate.isRequestCancelled) {
  226. return [OSSTask taskWithError:[NSError errorWithDomain:OSSClientErrorDomain
  227. code:OSSClientErrorCodeTaskCancelled
  228. userInfo:nil]];
  229. }
  230. [sessionTask resume];
  231. return task;
  232. }] continueWithBlock:^id(OSSTask *task) {
  233. // if error occurs before created sessionTask
  234. if (task.error) {
  235. requestDelegate.completionHandler(nil, task.error);
  236. } else if (task.isFaulted) {
  237. requestDelegate.completionHandler(nil, [NSError errorWithDomain:OSSClientErrorDomain
  238. code:OSSClientErrorCodeExcpetionCatched
  239. userInfo:@{OSSErrorMessageTOKEN: [NSString stringWithFormat:@"Catch exception - %@", task.exception]}]);
  240. }
  241. return nil;
  242. }];
  243. }
  244. #pragma mark - NSURLSessionTaskDelegate Methods
  245. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)sessionTask didCompleteWithError:(NSError *)error
  246. {
  247. OSSNetworkingRequestDelegate * delegate = [self.sessionDelagateManager objectForKey:@(sessionTask.taskIdentifier)];
  248. [self.sessionDelagateManager removeObjectForKey:@(sessionTask.taskIdentifier)];
  249. NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)sessionTask.response;
  250. if (delegate == nil) {
  251. OSSLogVerbose(@"delegate: %@", delegate);
  252. /* if the background transfer service is enable, may recieve the previous task complete callback */
  253. /* for now, we ignore it */
  254. return ;
  255. }
  256. NSString * dateStr = [[httpResponse allHeaderFields] objectForKey:@"Date"];
  257. if ([dateStr length]) {
  258. NSDate * serverTime = [NSDate oss_dateFromString:dateStr];
  259. NSDate * deviceTime = [NSDate date];
  260. NSTimeInterval skewTime = [deviceTime timeIntervalSinceDate:serverTime];
  261. [NSDate oss_setClockSkew:skewTime];
  262. } else {
  263. OSSLogError(@"date header does not exist, unable to adjust the time skew");
  264. }
  265. /* background upload task will not call back didRecieveResponse */
  266. if (delegate.isBackgroundUploadFileTask) {
  267. OSSLogVerbose(@"backgroud upload task did recieve response: %@", httpResponse);
  268. if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300 && httpResponse.statusCode != 203) {
  269. [delegate.responseParser consumeHttpResponse:httpResponse];
  270. } else {
  271. delegate.isHttpRequestNotSuccessResponse = YES;
  272. }
  273. }
  274. [[[[OSSTask taskWithResult:nil] continueWithSuccessBlock:^id(OSSTask * task) {
  275. if (!delegate.error) {
  276. delegate.error = error;
  277. }
  278. if (delegate.error) {
  279. OSSLogDebug(@"networking request completed with error: %@", error);
  280. if ([delegate.error.domain isEqualToString:NSURLErrorDomain] && delegate.error.code == NSURLErrorCancelled) {
  281. return [OSSTask taskWithError:[NSError errorWithDomain:OSSClientErrorDomain
  282. code:OSSClientErrorCodeTaskCancelled
  283. userInfo:[error userInfo]]];
  284. } else {
  285. NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithDictionary:[error userInfo]];
  286. [userInfo setObject:[NSString stringWithFormat:@"%ld", (long)error.code] forKey:@"OriginErrorCode"];
  287. return [OSSTask taskWithError:[NSError errorWithDomain:OSSClientErrorDomain
  288. code:OSSClientErrorCodeNetworkError
  289. userInfo:userInfo]];
  290. }
  291. }
  292. return task;
  293. }] continueWithSuccessBlock:^id(OSSTask *task) {
  294. if (delegate.isHttpRequestNotSuccessResponse) {
  295. if (httpResponse.statusCode == 0) {
  296. return [OSSTask taskWithError:[NSError errorWithDomain:OSSClientErrorDomain
  297. code:OSSClientErrorCodeNetworkingFailWithResponseCode0
  298. userInfo:@{OSSErrorMessageTOKEN: @"Request failed, response code 0"}]];
  299. }
  300. NSString * notSuccessResponseBody = [[NSString alloc] initWithData:delegate.httpRequestNotSuccessResponseBody encoding:NSUTF8StringEncoding];
  301. OSSLogError(@"http error response: %@", notSuccessResponseBody);
  302. NSDictionary * dict = [NSDictionary oss_dictionaryWithXMLString:notSuccessResponseBody];
  303. return [OSSTask taskWithError:[NSError errorWithDomain:OSSServerErrorDomain
  304. code:(-1 * httpResponse.statusCode)
  305. userInfo:dict]];
  306. }
  307. return task;
  308. }] continueWithBlock:^id(OSSTask *task) {
  309. if (task.error) {
  310. OSSNetworkingRetryType retryType = [delegate.retryHandler shouldRetry:delegate.currentRetryCount
  311. requestDelegate:delegate
  312. response:httpResponse
  313. error:task.error];
  314. OSSLogVerbose(@"current retry count: %u, retry type: %d", delegate.currentRetryCount, (int)retryType);
  315. switch (retryType) {
  316. case OSSNetworkingRetryTypeShouldNotRetry: {
  317. delegate.completionHandler(nil, task.error);
  318. return nil;
  319. }
  320. case OSSNetworkingRetryTypeShouldCorrectClockSkewAndRetry: {
  321. /* correct clock skew */
  322. [delegate.interceptors insertObject:[OSSTimeSkewedFixingInterceptor new] atIndex:0];
  323. break;
  324. }
  325. default:
  326. break;
  327. }
  328. /* now, should retry */
  329. NSTimeInterval suspendTime = [delegate.retryHandler timeIntervalForRetry:delegate.currentRetryCount retryType:retryType];
  330. delegate.currentRetryCount++;
  331. [NSThread sleepForTimeInterval:suspendTime];
  332. if(delegate.retryCallback){
  333. delegate.retryCallback();
  334. }
  335. /* retry recursively */
  336. [delegate reset];
  337. [self dataTaskWithDelegate:delegate];
  338. } else {
  339. delegate.completionHandler([delegate.responseParser constructResultObject], nil);
  340. }
  341. return nil;
  342. }];
  343. }
  344. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
  345. {
  346. OSSNetworkingRequestDelegate * delegate = [self.sessionDelagateManager objectForKey:@(task.taskIdentifier)];
  347. if (delegate.uploadProgress)
  348. {
  349. delegate.uploadProgress(bytesSent, totalBytesSent, totalBytesExpectedToSend);
  350. }
  351. }
  352. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler
  353. {
  354. if (!challenge) {
  355. return;
  356. }
  357. NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
  358. NSURLCredential *credential = nil;
  359. /*
  360. * Gets the host name
  361. */
  362. NSString * host = [[task.currentRequest allHTTPHeaderFields] objectForKey:@"Host"];
  363. if (!host) {
  364. host = task.currentRequest.URL.host;
  365. }
  366. if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
  367. if ([self evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) {
  368. disposition = NSURLSessionAuthChallengeUseCredential;
  369. credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
  370. }
  371. } else {
  372. disposition = NSURLSessionAuthChallengePerformDefaultHandling;
  373. }
  374. // Uses the default evaluation for other challenges.
  375. completionHandler(disposition,credential);
  376. }
  377. - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
  378. {
  379. }
  380. #pragma mark - NSURLSessionDataDelegate Methods
  381. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
  382. {
  383. OSSNetworkingRequestDelegate * delegate = [self.sessionDelagateManager objectForKey:@(dataTask.taskIdentifier)];
  384. /* background upload task will not call back didRecieveResponse */
  385. OSSLogVerbose(@"did receive response: %@", response);
  386. NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response;
  387. if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300 && httpResponse.statusCode != 203) {
  388. [delegate.responseParser consumeHttpResponse:httpResponse];
  389. } else {
  390. delegate.isHttpRequestNotSuccessResponse = YES;
  391. }
  392. completionHandler(NSURLSessionResponseAllow);
  393. }
  394. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
  395. {
  396. OSSNetworkingRequestDelegate * delegate = [self.sessionDelagateManager objectForKey:@(dataTask.taskIdentifier)];
  397. /* background upload task will not call back didRecieveResponse.
  398. so if we recieve response data after background uploading file,
  399. we consider it as error response message since a successful uploading request will not response any data */
  400. if (delegate.isBackgroundUploadFileTask)
  401. {
  402. //判断当前的statuscode是否成功
  403. NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)dataTask.response;
  404. if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300 && httpResponse.statusCode != 203) {
  405. [delegate.responseParser consumeHttpResponse:httpResponse];
  406. delegate.isHttpRequestNotSuccessResponse = NO;
  407. }else
  408. {
  409. delegate.isHttpRequestNotSuccessResponse = YES;
  410. }
  411. }
  412. if (delegate.isHttpRequestNotSuccessResponse) {
  413. [delegate.httpRequestNotSuccessResponseBody appendData:data];
  414. }
  415. else {
  416. if (delegate.onRecieveData) {
  417. delegate.onRecieveData(data);
  418. } else {
  419. OSSTask * consumeTask = [delegate.responseParser consumeHttpResponseBody:data];
  420. if (consumeTask.error) {
  421. OSSLogError(@"consume data error: %@", consumeTask.error);
  422. delegate.error = consumeTask.error;
  423. [dataTask cancel];
  424. }
  425. }
  426. }
  427. if (!delegate.isHttpRequestNotSuccessResponse && delegate.downloadProgress) {
  428. int64_t bytesWritten = [data length];
  429. delegate.payloadTotalBytesWritten += bytesWritten;
  430. int64_t totalBytesExpectedToWrite = dataTask.response.expectedContentLength;
  431. delegate.downloadProgress(bytesWritten, delegate.payloadTotalBytesWritten, totalBytesExpectedToWrite);
  432. }
  433. }
  434. #pragma mark - Private Methods
  435. - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {
  436. /*
  437. * Creates the policies for certificate verification.
  438. */
  439. NSMutableArray *policies = [NSMutableArray array];
  440. if (domain) {
  441. [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
  442. } else {
  443. [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
  444. }
  445. /*
  446. * Sets the policies to server's certificate
  447. */
  448. SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
  449. /*
  450. * Evaulates if the current serverTrust is trustable.
  451. * It's officially suggested that the serverTrust could be passed when result = kSecTrustResultUnspecified or kSecTrustResultProceed.
  452. * For more information checks out https://developer.apple.com/library/ios/technotes/tn2232/_index.html
  453. * For detail information about SecTrustResultType, checks out SecTrust.h
  454. */
  455. SecTrustResultType result;
  456. SecTrustEvaluate(serverTrust, &result);
  457. return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
  458. }
  459. @end