No Description

RNFetchBlobNetwork.m 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //
  2. // RNFetchBlobNetwork.m
  3. // RNFetchBlob
  4. //
  5. // Created by wkh237 on 2016/6/6.
  6. // Copyright © 2016 wkh237. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #import "RNFetchBlobNetwork.h"
  10. #import "RNFetchBlob.h"
  11. #import "RNFetchBlobConst.h"
  12. #import "RNFetchBlobProgress.h"
  13. #if __has_include(<React/RCTAssert.h>)
  14. #import <React/RCTRootView.h>
  15. #import <React/RCTLog.h>
  16. #import <React/RCTEventDispatcher.h>
  17. #import <React/RCTBridge.h>
  18. #else
  19. #import "RCTRootView.h"
  20. #import "RCTLog.h"
  21. #import "RCTEventDispatcher.h"
  22. #import "RCTBridge.h"
  23. #endif
  24. ////////////////////////////////////////
  25. //
  26. // HTTP request handler
  27. //
  28. ////////////////////////////////////////
  29. NSMapTable * expirationTable;
  30. __attribute__((constructor))
  31. static void initialize_tables() {
  32. if (expirationTable == nil) {
  33. expirationTable = [[NSMapTable alloc] init];
  34. }
  35. }
  36. @implementation RNFetchBlobNetwork
  37. - (id)init {
  38. self = [super init];
  39. if (self) {
  40. self.requestsTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableWeakMemory];
  41. self.taskQueue = [[NSOperationQueue alloc] init];
  42. self.taskQueue.qualityOfService = NSQualityOfServiceUtility;
  43. self.taskQueue.maxConcurrentOperationCount = 10;
  44. self.rebindProgressDict = [NSMutableDictionary dictionary];
  45. self.rebindUploadProgressDict = [NSMutableDictionary dictionary];
  46. }
  47. return self;
  48. }
  49. + (RNFetchBlobNetwork* _Nullable)sharedInstance {
  50. static id _sharedInstance = nil;
  51. static dispatch_once_t onceToken;
  52. dispatch_once(&onceToken, ^{
  53. _sharedInstance = [[self alloc] init];
  54. });
  55. return _sharedInstance;
  56. }
  57. - (void) sendRequest:(__weak NSDictionary * _Nullable )options
  58. contentLength:(long) contentLength
  59. bridge:(RCTBridge * _Nullable)bridgeRef
  60. taskId:(NSString * _Nullable)taskId
  61. withRequest:(__weak NSURLRequest * _Nullable)req
  62. callback:(_Nullable RCTResponseSenderBlock) callback
  63. {
  64. RNFetchBlobRequest *request = [[RNFetchBlobRequest alloc] init];
  65. [request sendRequest:options
  66. contentLength:contentLength
  67. bridge:bridgeRef
  68. taskId:taskId
  69. withRequest:req
  70. taskOperationQueue:self.taskQueue
  71. callback:callback];
  72. @synchronized([RNFetchBlobNetwork class]) {
  73. [self.requestsTable setObject:request forKey:taskId];
  74. [self checkProgressConfig];
  75. }
  76. }
  77. - (void) checkProgressConfig {
  78. //reconfig progress
  79. [self.rebindProgressDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, RNFetchBlobProgress * _Nonnull config, BOOL * _Nonnull stop) {
  80. [self enableProgressReport:key config:config];
  81. }];
  82. [self.rebindProgressDict removeAllObjects];
  83. //reconfig uploadProgress
  84. [self.rebindUploadProgressDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, RNFetchBlobProgress * _Nonnull config, BOOL * _Nonnull stop) {
  85. [self enableUploadProgress:key config:config];
  86. }];
  87. [self.rebindUploadProgressDict removeAllObjects];
  88. }
  89. - (void) enableProgressReport:(NSString *) taskId config:(RNFetchBlobProgress *)config
  90. {
  91. if (config) {
  92. @synchronized ([RNFetchBlobNetwork class]) {
  93. if (![self.requestsTable objectForKey:taskId]) {
  94. [self.rebindProgressDict setValue:config forKey:taskId];
  95. } else {
  96. [self.requestsTable objectForKey:taskId].progressConfig = config;
  97. }
  98. }
  99. }
  100. }
  101. - (void) enableUploadProgress:(NSString *) taskId config:(RNFetchBlobProgress *)config
  102. {
  103. if (config) {
  104. @synchronized ([RNFetchBlobNetwork class]) {
  105. if (![self.requestsTable objectForKey:taskId]) {
  106. [self.rebindUploadProgressDict setValue:config forKey:taskId];
  107. } else {
  108. [self.requestsTable objectForKey:taskId].uploadProgressConfig = config;
  109. }
  110. }
  111. }
  112. }
  113. - (void) cancelRequest:(NSString *)taskId
  114. {
  115. NSURLSessionDataTask * task;
  116. @synchronized ([RNFetchBlobNetwork class]) {
  117. task = [self.requestsTable objectForKey:taskId].task;
  118. }
  119. if (task && task.state == NSURLSessionTaskStateRunning) {
  120. [task cancel];
  121. }
  122. }
  123. // removing case from headers
  124. + (NSMutableDictionary *) normalizeHeaders:(NSDictionary *)headers
  125. {
  126. NSMutableDictionary * mheaders = [[NSMutableDictionary alloc]init];
  127. for (NSString * key in headers) {
  128. [mheaders setValue:[headers valueForKey:key] forKey:[key lowercaseString]];
  129. }
  130. return mheaders;
  131. }
  132. // #115 Invoke fetch.expire event on those expired requests so that the expired event can be handled
  133. + (void) emitExpiredTasks
  134. {
  135. @synchronized ([RNFetchBlobNetwork class]){
  136. NSEnumerator * emu = [expirationTable keyEnumerator];
  137. NSString * key;
  138. while ((key = [emu nextObject]))
  139. {
  140. RCTBridge * bridge = [RNFetchBlob getRCTBridge];
  141. id args = @{ @"taskId": key };
  142. [bridge.eventDispatcher sendDeviceEventWithName:EVENT_EXPIRE body:args];
  143. }
  144. // clear expired task entries
  145. [expirationTable removeAllObjects];
  146. expirationTable = [[NSMapTable alloc] init];
  147. }
  148. }
  149. @end