QNResponseInfo.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. //
  2. // QNResponseInfo.m
  3. // QiniuSDK
  4. //
  5. // Created by bailong on 14/10/2.
  6. // Copyright (c) 2014年 Qiniu. All rights reserved.
  7. //
  8. #import "QNResponseInfo.h"
  9. #import "QNUserAgent.h"
  10. #import "QNVersion.h"
  11. const int kQNZeroDataSize = -6;
  12. const int kQNInvalidToken = -5;
  13. const int kQNFileError = -4;
  14. const int kQNInvalidArgument = -3;
  15. const int kQNRequestCancelled = -2;
  16. const int kQNNetworkError = -1;
  17. /**
  18. https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/index.html#//apple_ref/doc/constant_group/URL_Loading_System_Error_Codes
  19. NSURLErrorUnknown = -1,
  20. NSURLErrorCancelled = -999,
  21. NSURLErrorBadURL = -1000,
  22. NSURLErrorTimedOut = -1001,
  23. NSURLErrorUnsupportedURL = -1002,
  24. NSURLErrorCannotFindHost = -1003,
  25. NSURLErrorCannotConnectToHost = -1004,
  26. NSURLErrorDataLengthExceedsMaximum = -1103,
  27. NSURLErrorNetworkConnectionLost = -1005,
  28. NSURLErrorDNSLookupFailed = -1006,
  29. NSURLErrorHTTPTooManyRedirects = -1007,
  30. NSURLErrorResourceUnavailable = -1008,
  31. NSURLErrorNotConnectedToInternet = -1009,
  32. NSURLErrorRedirectToNonExistentLocation = -1010,
  33. NSURLErrorBadServerResponse = -1011,
  34. NSURLErrorUserCancelledAuthentication = -1012,
  35. NSURLErrorUserAuthenticationRequired = -1013,
  36. NSURLErrorZeroByteResource = -1014,
  37. NSURLErrorCannotDecodeRawData = -1015,
  38. NSURLErrorCannotDecodeContentData = -1016,
  39. NSURLErrorCannotParseResponse = -1017,
  40. NSURLErrorInternationalRoamingOff = -1018,
  41. NSURLErrorCallIsActive = -1019,
  42. NSURLErrorDataNotAllowed = -1020,
  43. NSURLErrorRequestBodyStreamExhausted = -1021,
  44. NSURLErrorFileDoesNotExist = -1100,
  45. NSURLErrorFileIsDirectory = -1101,
  46. NSURLErrorNoPermissionsToReadFile = -1102,
  47. NSURLErrorSecureConnectionFailed = -1200,
  48. NSURLErrorServerCertificateHasBadDate = -1201,
  49. NSURLErrorServerCertificateUntrusted = -1202,
  50. NSURLErrorServerCertificateHasUnknownRoot = -1203,
  51. NSURLErrorServerCertificateNotYetValid = -1204,
  52. NSURLErrorClientCertificateRejected = -1205,
  53. NSURLErrorClientCertificateRequired = -1206,
  54. NSURLErrorCannotLoadFromNetwork = -2000,
  55. NSURLErrorCannotCreateFile = -3000,
  56. NSURLErrorCannotOpenFile = -3001,
  57. NSURLErrorCannotCloseFile = -3002,
  58. NSURLErrorCannotWriteToFile = -3003,
  59. NSURLErrorCannotRemoveFile = -3004,
  60. NSURLErrorCannotMoveFile = -3005,
  61. NSURLErrorDownloadDecodingFailedMidStream = -3006,
  62. NSURLErrorDownloadDecodingFailedToComplete = -3007
  63. */
  64. static QNResponseInfo *cancelledInfo = nil;
  65. static NSString *domain = @"qiniu.com";
  66. @implementation QNResponseInfo
  67. + (instancetype)cancel {
  68. return [[QNResponseInfo alloc] initWithCancelled];
  69. }
  70. + (instancetype)responseInfoWithInvalidArgument:(NSString *)text {
  71. return [[QNResponseInfo alloc] initWithStatus:kQNInvalidArgument errorDescription:text];
  72. }
  73. + (instancetype)responseInfoWithInvalidToken:(NSString *)text {
  74. return [[QNResponseInfo alloc] initWithStatus:kQNInvalidToken errorDescription:text];
  75. }
  76. + (instancetype)responseInfoWithNetError:(NSError *)error host:(NSString *)host duration:(double)duration {
  77. int code = kQNNetworkError;
  78. if (error != nil) {
  79. code = (int)error.code;
  80. }
  81. return [[QNResponseInfo alloc] initWithStatus:code error:error host:host duration:duration];
  82. }
  83. + (instancetype)responseInfoWithFileError:(NSError *)error {
  84. return [[QNResponseInfo alloc] initWithStatus:kQNFileError error:error];
  85. }
  86. + (instancetype)responseInfoOfZeroData:(NSString *)path {
  87. NSString *desc;
  88. if (path == nil) {
  89. desc = @"data size is 0";
  90. } else {
  91. desc = [[NSString alloc] initWithFormat:@"file %@ size is 0", path];
  92. }
  93. return [[QNResponseInfo alloc] initWithStatus:kQNZeroDataSize errorDescription:desc];
  94. }
  95. - (instancetype)initWithCancelled {
  96. return [self initWithStatus:kQNRequestCancelled errorDescription:@"cancelled by user"];
  97. }
  98. - (instancetype)initWithStatus:(int)status
  99. error:(NSError *)error {
  100. return [self initWithStatus:status error:error host:nil duration:0];
  101. }
  102. - (instancetype)initWithStatus:(int)status
  103. error:(NSError *)error
  104. host:(NSString *)host
  105. duration:(double)duration {
  106. if (self = [super init]) {
  107. _statusCode = status;
  108. _error = error;
  109. _host = host;
  110. _duration = duration;
  111. _id = [QNUserAgent sharedInstance].id;
  112. _timeStamp = [[NSDate date] timeIntervalSince1970];
  113. }
  114. return self;
  115. }
  116. - (instancetype)initWithStatus:(int)status
  117. errorDescription:(NSString *)text {
  118. NSError *error = [[NSError alloc] initWithDomain:domain code:status userInfo:@{ @"error" : text }];
  119. return [self initWithStatus:status error:error];
  120. }
  121. - (instancetype)init:(int)status
  122. withReqId:(NSString *)reqId
  123. withXLog:(NSString *)xlog
  124. withXVia:(NSString *)xvia
  125. withHost:(NSString *)host
  126. withIp:(NSString *)ip
  127. withDuration:(double)duration
  128. withBody:(NSData *)body {
  129. if (self = [super init]) {
  130. _statusCode = status;
  131. _reqId = reqId;
  132. _xlog = xlog;
  133. _xvia = xvia;
  134. _host = host;
  135. _duration = duration;
  136. _serverIp = ip;
  137. _id = [QNUserAgent sharedInstance].id;
  138. _timeStamp = [[NSDate date] timeIntervalSince1970];
  139. if (status != 200) {
  140. if (body == nil) {
  141. _error = [[NSError alloc] initWithDomain:domain code:_statusCode userInfo:nil];
  142. } else {
  143. NSError *tmp;
  144. NSDictionary *uInfo = [NSJSONSerialization JSONObjectWithData:body options:NSJSONReadingMutableLeaves error:&tmp];
  145. if (tmp != nil) {
  146. // 出现错误时,如果信息是非UTF8编码会失败,返回nil
  147. NSString *str = [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding];
  148. if (str == nil) {
  149. str = @"";
  150. }
  151. uInfo = @{ @"error" : str };
  152. }
  153. _error = [[NSError alloc] initWithDomain:domain code:_statusCode userInfo:uInfo];
  154. }
  155. } else if (body == nil || body.length == 0) {
  156. NSDictionary *uInfo = @{ @"error" : @"no response json" };
  157. _error = [[NSError alloc] initWithDomain:domain code:_statusCode userInfo:uInfo];
  158. }
  159. }
  160. return self;
  161. }
  162. - (NSString *)description {
  163. return [NSString stringWithFormat:@"<%@= id: %@, ver: %@, status: %d, requestId: %@, xlog: %@, xvia: %@, host: %@ ip: %@ duration: %f s time: %llu error: %@>", NSStringFromClass([self class]), _id, kQiniuVersion, _statusCode, _reqId, _xlog, _xvia, _host, _serverIp, _duration, _timeStamp, _error];
  164. }
  165. - (BOOL)isCancelled {
  166. return _statusCode == kQNRequestCancelled || _statusCode == -999;
  167. }
  168. - (BOOL)isNotQiniu {
  169. return (_statusCode >= 200 && _statusCode < 500) && _reqId == nil;
  170. }
  171. - (BOOL)isOK {
  172. return _statusCode == 200 && _error == nil && _reqId != nil;
  173. }
  174. - (BOOL)isConnectionBroken {
  175. // reqId is nill means the server is not qiniu
  176. return _statusCode == kQNNetworkError || (_statusCode < -1000 && _statusCode != -1003);
  177. }
  178. - (BOOL)needSwitchServer {
  179. return _statusCode == kQNNetworkError || (_statusCode < -1000 && _statusCode != -1003) || (_statusCode / 100 == 5 && _statusCode != 579);
  180. }
  181. - (BOOL)couldRetry {
  182. return (_statusCode >= 500 && _statusCode < 600 && _statusCode != 579) || _statusCode == kQNNetworkError || _statusCode == 996 || _statusCode == 406 || (_statusCode == 200 && _error != nil) || _statusCode < -1000 || self.isNotQiniu;
  183. }
  184. @end