Skip to content
This repository was archived by the owner on Mar 16, 2019. It is now read-only.

Commit a07b93a

Browse files
committed
Fix IOS task queue race condition issue when sending massive requests
Fix #72 status code except 2xx will now causing a promise rejection
1 parent 195499a commit a07b93a

File tree

2 files changed

+57
-29
lines changed

2 files changed

+57
-29
lines changed

src/ios/RNFetchBlobFS.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@ + (NSNumber *) writeFileFromFile:(NSString *)src toFile:(NSString *)dest append:
207207

208208
+ (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject
209209
{
210-
NSLog(encoding);
211210
@try {
212211
NSFileManager * fm = [NSFileManager defaultManager];
213212
NSError * err = nil;

src/ios/RNFetchBlobNetwork.m

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@
2323
//
2424
////////////////////////////////////////
2525

26-
NSMutableDictionary * taskTable;
26+
NSMapTable * taskTable;
2727
NSMutableDictionary * progressTable;
2828
NSMutableDictionary * uploadProgressTable;
2929

30+
3031
@interface RNFetchBlobNetwork ()
3132
{
3233
BOOL * respFile;
3334
NSString * destPath;
3435
NSOutputStream * writeStream;
3536
long bodyLength;
3637
NSMutableDictionary * respInfo;
38+
NSInteger respStatus;
3739
}
3840

3941
@end
@@ -61,7 +63,7 @@ - (id)init {
6163
taskQueue.maxConcurrentOperationCount = 10;
6264
}
6365
if(taskTable == nil) {
64-
taskTable = [[NSMutableDictionary alloc] init];
66+
taskTable = [[NSMapTable alloc] init];
6567
}
6668
if(progressTable == nil)
6769
{
@@ -139,6 +141,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
139141
{
140142
defaultConfigObject.timeoutIntervalForRequest = [[options valueForKey:@"timeout"] floatValue]/1000;
141143
}
144+
defaultConfigObject.HTTPMaximumConnectionsPerHost = 10;
142145
session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:taskQueue];
143146
if(path != nil || [self.options valueForKey:CONFIG_USE_TEMP]!= nil)
144147
{
@@ -193,6 +196,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
193196

194197
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
195198
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
199+
respStatus = statusCode;
196200
if ([response respondsToSelector:@selector(allHeaderFields)])
197201
{
198202
NSDictionary *headers = [httpResponse allHeaderFields];
@@ -242,7 +246,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
242246
@"respType" : respType,
243247
@"timeout" : @NO,
244248
@"status": [NSString stringWithFormat:@"%d", statusCode ]
245-
};
249+
};
246250

247251
[self.bridge.eventDispatcher
248252
sendDeviceEventWithName: EVENT_STATE_CHANGE
@@ -270,6 +274,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
270274
NSLog(@"write file error");
271275
}
272276
}
277+
273278
completionHandler(NSURLSessionResponseAllow);
274279
}
275280

@@ -312,42 +317,66 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
312317
{
313318

314319
self.error = error;
315-
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
316-
320+
NSString * errMsg = [NSNull null];
321+
NSString * respStr = [NSNull null];
317322
NSString * respType = [respInfo valueForKey:@"respType"];
318-
if(error != nil) {
319-
NSLog([error localizedDescription]);
323+
324+
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
325+
if(error != nil)
326+
{
327+
errMsg = [error localizedDescription];
328+
}
329+
if(respInfo == nil)
330+
{
331+
respInfo = [NSNull null];
320332
}
321333

322-
if(respFile == YES)
334+
// Fix #72 response with status code 200 ~ 299 considered as success
335+
if(respStatus> 299 || respStatus < 200)
336+
{
337+
errMsg = [NSString stringWithFormat:@"Request failed, status %d", respStatus];
338+
}
339+
else
323340
{
324-
[writeStream close];
325-
callback(@[error == nil ? [NSNull null] : [error localizedDescription],
326-
respInfo == nil ? [NSNull null] : respInfo,
327-
destPath
328-
]);
341+
if(respFile == YES)
342+
{
343+
[writeStream close];
344+
respStr = destPath;
345+
}
346+
// base64 response
347+
else {
348+
// #73 fix unicode data encoding issue :
349+
// when response type is BASE64, we should first try to encode the response data to UTF8 format
350+
// if it turns out not to be `nil` that means the response data contains valid UTF8 string,
351+
// in order to properly encode the UTF8 string, use URL encoding before BASE64 encoding.
352+
NSString * urlEncoded = [[[NSString alloc] initWithData:respData encoding:NSUTF8StringEncoding]
353+
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
354+
NSString * base64 = @"";
355+
if(urlEncoded != nil)
356+
base64 = [[urlEncoded dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
357+
else
358+
base64 = [respData base64EncodedStringWithOptions:0];
359+
respStr = base64;
360+
361+
}
329362
}
330-
// base64 response
331-
else {
332-
NSString * utf8 = [[[NSString alloc] initWithData:respData encoding:NSUTF8StringEncoding] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
333-
NSString * base64 = @"";
334-
if(utf8 != nil)
335-
base64 = [[utf8 dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
363+
364+
callback(@[ errMsg, respInfo, respStr ]);
365+
366+
@synchronized(taskTable, uploadProgressTable, progressTable)
367+
{
368+
if([taskTable objectForKey:taskId] == nil)
369+
NSLog(@"object released.");
336370
else
337-
base64 = [respData base64EncodedStringWithOptions:0];
338-
callback(@[error == nil ? [NSNull null] : [error localizedDescription],
339-
respInfo == nil ? [NSNull null] : respInfo,
340-
base64
341-
]);
342-
371+
[taskTable removeObjectForKey:taskId];
372+
[uploadProgressTable removeObjectForKey:taskId];
373+
[progressTable removeObjectForKey:taskId];
343374
}
344375

345-
[taskTable removeObjectForKey:taskId];
346-
[uploadProgressTable removeObjectForKey:taskId];
347-
[progressTable removeObjectForKey:taskId];
348376
respData = nil;
349377
receivedBytes = 0;
350378
[session finishTasksAndInvalidate];
379+
351380
}
352381

353382
// upload progress handler

0 commit comments

Comments
 (0)