QNHttpRegionRequest.m 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. //
  2. // QNHttpRequest.m
  3. // QiniuSDK
  4. //
  5. // Created by yangsen on 2020/4/29.
  6. // Copyright © 2020 Qiniu. All rights reserved.
  7. //
  8. #import "QNDefine.h"
  9. #import "QNLogUtil.h"
  10. #import "QNAsyncRun.h"
  11. #import "QNHttpRegionRequest.h"
  12. #import "QNConfiguration.h"
  13. #import "QNUploadOption.h"
  14. #import "NSURLRequest+QNRequest.h"
  15. #import "QNUploadRequestMetrics.h"
  16. #import "QNResponseInfo.h"
  17. @interface QNHttpRegionRequest()
  18. @property(nonatomic, strong)QNConfiguration *config;
  19. @property(nonatomic, strong)QNUploadOption *uploadOption;
  20. @property(nonatomic, strong)QNUploadRequestInfo *requestInfo;
  21. @property(nonatomic, strong)QNUploadRequestState *requestState;
  22. @property(nonatomic, strong)QNUploadRegionRequestMetrics *requestMetrics;
  23. @property(nonatomic, strong)QNHttpSingleRequest *singleRequest;
  24. // old server 不验证tls sni
  25. @property(nonatomic, assign)BOOL isUseOldServer;
  26. @property(nonatomic, strong)id <QNUploadServer> currentServer;
  27. @property(nonatomic, strong)id <QNUploadRegion> region;
  28. @end
  29. @implementation QNHttpRegionRequest
  30. - (instancetype)initWithConfig:(QNConfiguration *)config
  31. uploadOption:(QNUploadOption *)uploadOption
  32. token:(QNUpToken *)token
  33. region:(id <QNUploadRegion>)region
  34. requestInfo:(QNUploadRequestInfo *)requestInfo
  35. requestState:(QNUploadRequestState *)requestState {
  36. if (self = [super init]) {
  37. _config = config;
  38. _uploadOption = uploadOption;
  39. _region = region;
  40. _requestInfo = requestInfo;
  41. _requestState = requestState;
  42. _singleRequest = [[QNHttpSingleRequest alloc] initWithConfig:config
  43. uploadOption:uploadOption
  44. token:token
  45. requestInfo:requestInfo
  46. requestState:requestState];
  47. }
  48. return self;
  49. }
  50. - (void)get:(NSString *)action
  51. headers:(NSDictionary *)headers
  52. shouldRetry:(BOOL(^)(QNResponseInfo *responseInfo, NSDictionary *response))shouldRetry
  53. complete:(QNRegionRequestCompleteHandler)complete{
  54. self.requestMetrics = [[QNUploadRegionRequestMetrics alloc] initWithRegion:self.region];
  55. [self performRequest:[self getNextServer:nil]
  56. action:action
  57. headers:headers
  58. method:@"GET"
  59. body:nil
  60. shouldRetry:shouldRetry
  61. progress:nil
  62. complete:complete];
  63. }
  64. - (void)post:(NSString *)action
  65. headers:(NSDictionary *)headers
  66. body:(NSData *)body
  67. shouldRetry:(BOOL(^)(QNResponseInfo *responseInfo, NSDictionary *response))shouldRetry
  68. progress:(void(^)(long long totalBytesWritten, long long totalBytesExpectedToWrite))progress
  69. complete:(QNRegionRequestCompleteHandler)complete{
  70. self.requestMetrics = [[QNUploadRegionRequestMetrics alloc] initWithRegion:self.region];
  71. [self performRequest:[self getNextServer:nil]
  72. action:action
  73. headers:headers
  74. method:@"POST"
  75. body:body
  76. shouldRetry:shouldRetry
  77. progress:progress
  78. complete:complete];
  79. }
  80. - (void)put:(NSString *)action
  81. headers:(NSDictionary *)headers
  82. body:(NSData *)body
  83. shouldRetry:(BOOL(^)(QNResponseInfo *responseInfo, NSDictionary *response))shouldRetry
  84. progress:(void(^)(long long totalBytesWritten, long long totalBytesExpectedToWrite))progress
  85. complete:(QNRegionRequestCompleteHandler)complete{
  86. self.requestMetrics = [[QNUploadRegionRequestMetrics alloc] initWithRegion:self.region];
  87. [self performRequest:[self getNextServer:nil]
  88. action:action
  89. headers:headers
  90. method:@"PUT"
  91. body:body
  92. shouldRetry:shouldRetry
  93. progress:progress
  94. complete:complete];
  95. }
  96. - (void)performRequest:(id <QNUploadServer>)server
  97. action:(NSString *)action
  98. headers:(NSDictionary *)headers
  99. method:(NSString *)method
  100. body:(NSData *)body
  101. shouldRetry:(BOOL(^)(QNResponseInfo *responseInfo, NSDictionary *response))shouldRetry
  102. progress:(void(^)(long long totalBytesWritten, long long totalBytesExpectedToWrite))progress
  103. complete:(QNRegionRequestCompleteHandler)complete{
  104. if (!server.host || server.host.length == 0) {
  105. QNResponseInfo *responseInfo = [QNResponseInfo responseInfoWithSDKInteriorError:@"server error"];
  106. [self complete:responseInfo response:nil complete:complete];
  107. return;
  108. }
  109. NSString *serverHost = server.host;
  110. NSString *serverIP = server.ip;
  111. if (self.config.converter) {
  112. serverHost = self.config.converter(serverHost);
  113. serverIP = nil;
  114. }
  115. self.currentServer = server;
  116. BOOL toSkipDns = NO;
  117. NSString *scheme = self.config.useHttps ? @"https://" : @"http://";
  118. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  119. if (serverIP && serverIP.length > 0) {
  120. NSString *urlString = [NSString stringWithFormat:@"%@%@%@", scheme, serverIP, action ?: @""];
  121. request.URL = [NSURL URLWithString:urlString];
  122. request.qn_domain = serverHost;
  123. request.qn_ip = serverIP;
  124. toSkipDns = YES;
  125. } else {
  126. NSString *urlString = [NSString stringWithFormat:@"%@%@%@", scheme, serverHost, action ?: @""];
  127. request.URL = [NSURL URLWithString:urlString];
  128. request.qn_domain = serverHost;
  129. request.qn_ip = nil;
  130. toSkipDns = NO;
  131. }
  132. request.HTTPMethod = method;
  133. [request setAllHTTPHeaderFields:headers];
  134. [request setTimeoutInterval:self.config.timeoutInterval];
  135. request.HTTPBody = body;
  136. QNLogInfo(@"key:%@ url:%@", self.requestInfo.key, request.URL);
  137. QNLogInfo(@"key:%@ headers:%@", self.requestInfo.key, headers);
  138. kQNWeakSelf;
  139. [self.singleRequest request:request
  140. server:server
  141. toSkipDns:toSkipDns
  142. shouldRetry:shouldRetry
  143. progress:progress
  144. complete:^(QNResponseInfo * _Nullable responseInfo, NSArray<QNUploadSingleRequestMetrics *> * _Nullable metrics, NSDictionary * _Nullable response) {
  145. kQNStrongSelf;
  146. [self.requestMetrics addMetricsList:metrics];
  147. if (shouldRetry(responseInfo, response)
  148. && self.config.allowBackupHost
  149. && responseInfo.couldRegionRetry) {
  150. id <QNUploadServer> newServer = [self getNextServer:responseInfo];
  151. if (newServer) {
  152. QNAsyncRunAfter(self.config.retryInterval, kQNBackgroundQueue, ^{
  153. [self performRequest:newServer
  154. action:action
  155. headers:headers
  156. method:method
  157. body:body
  158. shouldRetry:shouldRetry
  159. progress:progress
  160. complete:complete];
  161. });
  162. } else if (complete) {
  163. [self complete:responseInfo response:response complete:complete];
  164. }
  165. } else if (complete) {
  166. [self complete:responseInfo response:response complete:complete];
  167. }
  168. }];
  169. }
  170. - (void)complete:(QNResponseInfo *)responseInfo
  171. response:(NSDictionary *)response
  172. complete:(QNRegionRequestCompleteHandler)completionHandler {
  173. self.singleRequest = nil;
  174. if (completionHandler) {
  175. completionHandler(responseInfo, self.requestMetrics, response);
  176. }
  177. }
  178. //MARK: --
  179. - (id <QNUploadServer>)getNextServer:(QNResponseInfo *)responseInfo{
  180. if (responseInfo.isTlsError) {
  181. self.isUseOldServer = YES;
  182. }
  183. return [self.region getNextServer:self.isUseOldServer responseInfo:responseInfo freezeServer:self.currentServer];
  184. }
  185. @end