QNUploadSystemClient.m 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. //
  2. // QNUploadSystemClient.m
  3. // QiniuSDK_Mac
  4. //
  5. // Created by yangsen on 2020/5/6.
  6. // Copyright © 2020 Qiniu. All rights reserved.
  7. //
  8. #import "QNUploadSystemClient.h"
  9. #import "QNUserAgent.h"
  10. #import "NSURLRequest+QNRequest.h"
  11. @interface QNUploadSystemClient()<NSURLSessionDelegate>
  12. @property(nonatomic, strong)NSURLRequest *request;
  13. @property(nonatomic, strong)QNUploadSingleRequestMetrics *requestMetrics;
  14. @property(nonatomic, strong)NSURLSessionDataTask *uploadTask;
  15. @property(nonatomic, strong)NSMutableData *responseData;
  16. @property(nonatomic, copy)void(^progress)(long long totalBytesWritten, long long totalBytesExpectedToWrite);
  17. @property(nonatomic, copy)QNRequestClientCompleteHandler complete;
  18. @end
  19. @implementation QNUploadSystemClient
  20. - (NSString *)clientId {
  21. return @"NSURLSession";
  22. }
  23. - (void)request:(NSURLRequest *)request
  24. server:(id <QNUploadServer>)server
  25. connectionProxy:(NSDictionary *)connectionProxy
  26. progress:(void (^)(long long, long long))progress
  27. complete:(QNRequestClientCompleteHandler)complete {
  28. // 非 https 方可使用 IP
  29. if (!request.qn_isHttps && server && server.ip.length > 0 && server.host.length > 0) {
  30. NSString *urlString = request.URL.absoluteString;
  31. urlString = [urlString stringByReplacingOccurrencesOfString:server.host withString:server.ip];
  32. NSMutableURLRequest *requestNew = [request mutableCopy];
  33. requestNew.URL = [NSURL URLWithString:urlString];
  34. requestNew.qn_domain = server.host;
  35. self.request = [requestNew copy];
  36. } else {
  37. self.request = request;
  38. }
  39. self.requestMetrics = [QNUploadSingleRequestMetrics emptyMetrics];
  40. self.requestMetrics.remoteAddress = self.request.qn_isHttps ? nil : server.ip;
  41. self.requestMetrics.remotePort = self.request.qn_isHttps ? @443 : @80;
  42. [self.requestMetrics start];
  43. self.responseData = [NSMutableData data];
  44. self.progress = progress;
  45. self.complete = complete;
  46. NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  47. if (connectionProxy) {
  48. configuration.connectionProxyDictionary = connectionProxy;
  49. }
  50. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  51. delegate:self
  52. delegateQueue:nil];
  53. NSURLSessionDataTask *uploadTask = [session dataTaskWithRequest:self.request];
  54. [uploadTask resume];
  55. self.uploadTask = uploadTask;
  56. }
  57. - (void)cancel{
  58. [self.uploadTask cancel];
  59. }
  60. //MARK:-- NSURLSessionDelegate
  61. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
  62. completionHandler(NSURLSessionResponseAllow);
  63. }
  64. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
  65. [self.responseData appendData:data];
  66. }
  67. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error {
  68. [self.requestMetrics end];
  69. self.requestMetrics.request = task.currentRequest;
  70. self.requestMetrics.response = task.response;
  71. self.requestMetrics.error = error;
  72. self.complete(task.response, self.requestMetrics,self.responseData, error);
  73. [session finishTasksAndInvalidate];
  74. }
  75. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics API_AVAILABLE(ios(10.0)) {
  76. NSURLSessionTaskTransactionMetrics *transactionMetrics = metrics.transactionMetrics.lastObject;
  77. self.requestMetrics.domainLookupStartDate = transactionMetrics.domainLookupStartDate;
  78. self.requestMetrics.domainLookupEndDate = transactionMetrics.domainLookupEndDate;
  79. self.requestMetrics.connectStartDate = transactionMetrics.connectStartDate;
  80. self.requestMetrics.secureConnectionStartDate = transactionMetrics.secureConnectionStartDate;
  81. self.requestMetrics.secureConnectionEndDate = transactionMetrics.secureConnectionEndDate;
  82. self.requestMetrics.connectEndDate = transactionMetrics.connectEndDate;
  83. self.requestMetrics.requestStartDate = transactionMetrics.requestStartDate;
  84. self.requestMetrics.requestEndDate = transactionMetrics.requestEndDate;
  85. self.requestMetrics.responseStartDate = transactionMetrics.responseStartDate;
  86. self.requestMetrics.responseEndDate = transactionMetrics.responseEndDate;
  87. if ([transactionMetrics.networkProtocolName isEqualToString:@"http/1.0"]) {
  88. self.requestMetrics.httpVersion = @"1.0";
  89. } else if ([transactionMetrics.networkProtocolName isEqualToString:@"http/1.1"]) {
  90. self.requestMetrics.httpVersion = @"1.1";
  91. } else if ([transactionMetrics.networkProtocolName isEqualToString:@"h2"]) {
  92. self.requestMetrics.httpVersion = @"2";
  93. } else if ([transactionMetrics.networkProtocolName isEqualToString:@"h3"]) {
  94. self.requestMetrics.httpVersion = @"3";
  95. } else {
  96. self.requestMetrics.httpVersion = transactionMetrics.networkProtocolName;
  97. }
  98. #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
  99. if (@available(iOS 13.0, macOS 10.15, *)) {
  100. if (transactionMetrics.remoteAddress) {
  101. self.requestMetrics.remoteAddress = transactionMetrics.remoteAddress;
  102. self.requestMetrics.remotePort = transactionMetrics.remotePort;
  103. }
  104. if (transactionMetrics.countOfRequestHeaderBytesSent > 0) {
  105. self.requestMetrics.countOfRequestHeaderBytesSent = transactionMetrics.countOfRequestHeaderBytesSent;
  106. }
  107. if (transactionMetrics.countOfResponseHeaderBytesReceived > 0) {
  108. self.requestMetrics.countOfResponseHeaderBytesReceived = transactionMetrics.countOfResponseHeaderBytesReceived;
  109. }
  110. if (transactionMetrics.countOfResponseBodyBytesReceived > 0) {
  111. self.requestMetrics.countOfResponseBodyBytesReceived = transactionMetrics.countOfResponseBodyBytesReceived;
  112. }
  113. }
  114. #endif
  115. }
  116. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
  117. didSendBodyData:(int64_t)bytesSent
  118. totalBytesSent:(int64_t)totalBytesSent
  119. totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
  120. self.requestMetrics.countOfRequestBodyBytesSent = totalBytesSent;
  121. if (self.progress) {
  122. self.progress(totalBytesSent, totalBytesExpectedToSend);
  123. }
  124. }
  125. /*
  126. - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
  127. forDomain:(NSString *)domain {
  128. NSMutableArray *policies = [NSMutableArray array];
  129. if (domain) {
  130. [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
  131. } else {
  132. [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
  133. }
  134. SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
  135. if (@available(iOS 13.0, macOS 10.14, *)) {
  136. CFErrorRef error = NULL;
  137. BOOL ret = SecTrustEvaluateWithError(serverTrust, &error);
  138. return ret && (error == nil);
  139. } else {
  140. SecTrustResultType result;
  141. SecTrustEvaluate(serverTrust, &result);
  142. return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
  143. }
  144. }
  145. - (void)URLSession:(NSURLSession *)session
  146. task:(NSURLSessionTask *)task
  147. didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
  148. completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {
  149. if (!challenge) {
  150. return;
  151. }
  152. NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
  153. NSURLCredential *credential = nil;
  154. NSString* host = [[self.request allHTTPHeaderFields] objectForKey:@"host"];
  155. if (!host) {
  156. host = self.request.URL.host;
  157. }
  158. if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
  159. if ([self evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) {
  160. disposition = NSURLSessionAuthChallengeUseCredential;
  161. credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
  162. } else {
  163. disposition = NSURLSessionAuthChallengePerformDefaultHandling;
  164. }
  165. } else {
  166. disposition = NSURLSessionAuthChallengePerformDefaultHandling;
  167. }
  168. completionHandler(disposition,credential);
  169. }
  170. */
  171. @end