AFHTTPRequestOperation.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // AFHTTPRequestOperation.m
  2. // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/)
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. #import "AFHTTPRequestOperation.h"
  22. static dispatch_queue_t http_request_operation_processing_queue() {
  23. static dispatch_queue_t af_http_request_operation_processing_queue;
  24. static dispatch_once_t onceToken;
  25. dispatch_once(&onceToken, ^{
  26. af_http_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.http-request.processing", DISPATCH_QUEUE_CONCURRENT);
  27. });
  28. return af_http_request_operation_processing_queue;
  29. }
  30. static dispatch_group_t http_request_operation_completion_group() {
  31. static dispatch_group_t af_http_request_operation_completion_group;
  32. static dispatch_once_t onceToken;
  33. dispatch_once(&onceToken, ^{
  34. af_http_request_operation_completion_group = dispatch_group_create();
  35. });
  36. return af_http_request_operation_completion_group;
  37. }
  38. #pragma mark -
  39. @interface AFURLConnectionOperation ()
  40. @property (readwrite, nonatomic, strong) NSURLRequest *request;
  41. @property (readwrite, nonatomic, strong) NSURLResponse *response;
  42. @end
  43. @interface AFHTTPRequestOperation ()
  44. @property (readwrite, nonatomic, strong) NSHTTPURLResponse *response;
  45. @property (readwrite, nonatomic, strong) id responseObject;
  46. @property (readwrite, nonatomic, strong) NSError *responseSerializationError;
  47. @property (readwrite, nonatomic, strong) NSRecursiveLock *lock;
  48. @end
  49. @implementation AFHTTPRequestOperation
  50. @dynamic response;
  51. @dynamic lock;
  52. - (instancetype)initWithRequest:(NSURLRequest *)urlRequest {
  53. self = [super initWithRequest:urlRequest];
  54. if (!self) {
  55. return nil;
  56. }
  57. self.responseSerializer = [AFHTTPResponseSerializer serializer];
  58. return self;
  59. }
  60. - (void)setResponseSerializer:(AFHTTPResponseSerializer <AFURLResponseSerialization> *)responseSerializer {
  61. NSParameterAssert(responseSerializer);
  62. [self.lock lock];
  63. _responseSerializer = responseSerializer;
  64. self.responseObject = nil;
  65. self.responseSerializationError = nil;
  66. [self.lock unlock];
  67. }
  68. - (id)responseObject {
  69. [self.lock lock];
  70. if (!_responseObject && [self isFinished] && !self.error) {
  71. NSError *error = nil;
  72. self.responseObject = [self.responseSerializer responseObjectForResponse:self.response data:self.responseData error:&error];
  73. if (error) {
  74. self.responseSerializationError = error;
  75. }
  76. }
  77. [self.lock unlock];
  78. return _responseObject;
  79. }
  80. - (NSError *)error {
  81. if (_responseSerializationError) {
  82. return _responseSerializationError;
  83. } else {
  84. return [super error];
  85. }
  86. }
  87. #pragma mark - AFHTTPRequestOperation
  88. - (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
  89. failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
  90. {
  91. // completionBlock is manually nilled out in AFURLConnectionOperation to break the retain cycle.
  92. #pragma clang diagnostic push
  93. #pragma clang diagnostic ignored "-Warc-retain-cycles"
  94. #pragma clang diagnostic ignored "-Wgnu"
  95. self.completionBlock = ^{
  96. if (self.completionGroup) {
  97. dispatch_group_enter(self.completionGroup);
  98. }
  99. dispatch_async(http_request_operation_processing_queue(), ^{
  100. if (self.error) {
  101. if (failure) {
  102. dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
  103. failure(self, self.error);
  104. });
  105. }
  106. } else {
  107. id responseObject = self.responseObject;
  108. if (self.error) {
  109. if (failure) {
  110. dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
  111. failure(self, self.error);
  112. });
  113. }
  114. } else {
  115. if (success) {
  116. dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
  117. success(self, responseObject);
  118. });
  119. }
  120. }
  121. }
  122. if (self.completionGroup) {
  123. dispatch_group_leave(self.completionGroup);
  124. }
  125. });
  126. };
  127. #pragma clang diagnostic pop
  128. }
  129. #pragma mark - AFURLRequestOperation
  130. - (void)pause {
  131. [super pause];
  132. u_int64_t offset = 0;
  133. if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) {
  134. offset = [(NSNumber *)[self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey] unsignedLongLongValue];
  135. } else {
  136. offset = [(NSData *)[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length];
  137. }
  138. NSMutableURLRequest *mutableURLRequest = [self.request mutableCopy];
  139. if ([self.response respondsToSelector:@selector(allHeaderFields)] && [[self.response allHeaderFields] valueForKey:@"ETag"]) {
  140. [mutableURLRequest setValue:[[self.response allHeaderFields] valueForKey:@"ETag"] forHTTPHeaderField:@"If-Range"];
  141. }
  142. [mutableURLRequest setValue:[NSString stringWithFormat:@"bytes=%llu-", offset] forHTTPHeaderField:@"Range"];
  143. self.request = mutableURLRequest;
  144. }
  145. #pragma mark - NSSecureCoding
  146. + (BOOL)supportsSecureCoding {
  147. return YES;
  148. }
  149. - (id)initWithCoder:(NSCoder *)decoder {
  150. self = [super initWithCoder:decoder];
  151. if (!self) {
  152. return nil;
  153. }
  154. self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))];
  155. return self;
  156. }
  157. - (void)encodeWithCoder:(NSCoder *)coder {
  158. [super encodeWithCoder:coder];
  159. [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))];
  160. }
  161. #pragma mark - NSCopying
  162. - (id)copyWithZone:(NSZone *)zone {
  163. AFHTTPRequestOperation *operation = [super copyWithZone:zone];
  164. operation.responseSerializer = [self.responseSerializer copyWithZone:zone];
  165. operation.completionQueue = self.completionQueue;
  166. operation.completionGroup = self.completionGroup;
  167. return operation;
  168. }
  169. @end