Files
react-native/Libraries/Network/RCTHTTPRequestHandler.mm
T
zhongwuzw 916186a7e6 Change ReactNetworkForceWifiOnly from String to Boolean (#24829)
Summary:
We provided `ReactNetworkForceWifiOnly` in https://github.com/facebook/react-native/pull/24242, but it's a string type, actually the value only YES or NO, so let's change it to Boolean type, we can benefit from:
1. Users don't need to type string `YES`, just select bool YES or NO directly by click the button:
<img width="789" alt="image" src="https://user-images.githubusercontent.com/5061845/57634311-a8af7400-75d7-11e9-9f8a-ebf865d672e3.png">

2. Don't need to do string compare.

3. More looks what it should looks, Boolean is the Boolean. :)

cc. cpojer ericlewis .

[iOS] [Changed] - Change ReactNetworkForceWifiOnly from String to Boolean
Pull Request resolved: https://github.com/facebook/react-native/pull/24829

Differential Revision: D15323685

Pulled By: cpojer

fbshipit-source-id: c626d048d0cbea46d45f232906fd3ac32a412741
2019-05-14 02:50:21 -07:00

181 lines
5.9 KiB
Plaintext

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTHTTPRequestHandler.h"
#import <mutex>
#import "RCTNetworking.h"
@interface RCTHTTPRequestHandler () <NSURLSessionDataDelegate>
@end
@implementation RCTHTTPRequestHandler
{
NSMapTable *_delegates;
NSURLSession *_session;
std::mutex _mutex;
}
@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue;
RCT_EXPORT_MODULE()
- (void)invalidate
{
dispatch_async(self->_methodQueue, ^{
[self->_session invalidateAndCancel];
self->_session = nil;
});
}
- (BOOL)isValid
{
// if session == nil and delegates != nil, we've been invalidated
return _session || !_delegates;
}
#pragma mark - NSURLRequestHandler
- (BOOL)canHandleRequest:(NSURLRequest *)request
{
static NSSet<NSString *> *schemes = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// technically, RCTHTTPRequestHandler can handle file:// as well,
// but it's less efficient than using RCTFileRequestHandler
schemes = [[NSSet alloc] initWithObjects:@"http", @"https", nil];
});
return [schemes containsObject:request.URL.scheme.lowercaseString];
}
- (NSURLSessionDataTask *)sendRequest:(NSURLRequest *)request
withDelegate:(id<RCTURLRequestDelegate>)delegate
{
// Lazy setup
if (!_session && [self isValid]) {
// You can override default NSURLSession instance property allowsCellularAccess (default value YES)
// by providing the following key to your RN project (edit ios/project/Info.plist file in Xcode):
// <key>ReactNetworkForceWifiOnly</key> <true/>
// This will set allowsCellularAccess to NO and force Wifi only for all network calls on iOS
// If you do not want to override default behavior, do nothing or set key with value false
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSNumber *useWifiOnly = [infoDictionary objectForKey:@"ReactNetworkForceWifiOnly"];
NSOperationQueue *callbackQueue = [NSOperationQueue new];
callbackQueue.maxConcurrentOperationCount = 1;
callbackQueue.underlyingQueue = [[_bridge networking] methodQueue];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// Set allowsCellularAccess to NO ONLY if key ReactNetworkForceWifiOnly exists AND its value is YES
if (useWifiOnly) {
configuration.allowsCellularAccess = ![useWifiOnly boolValue];
}
[configuration setHTTPShouldSetCookies:YES];
[configuration setHTTPCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
[configuration setHTTPCookieStorage:[NSHTTPCookieStorage sharedHTTPCookieStorage]];
_session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:callbackQueue];
std::lock_guard<std::mutex> lock(_mutex);
_delegates = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory
valueOptions:NSPointerFunctionsStrongMemory
capacity:0];
}
__block NSURLSessionDataTask *task = nil;
dispatch_sync(self->_methodQueue, ^{
task = [self->_session dataTaskWithRequest:request];
});
{
std::lock_guard<std::mutex> lock(_mutex);
[_delegates setObject:delegate forKey:task];
}
[task resume];
return task;
}
- (void)cancelRequest:(NSURLSessionDataTask *)task
{
{
std::lock_guard<std::mutex> lock(_mutex);
[_delegates removeObjectForKey:task];
}
[task cancel];
}
#pragma mark - NSURLSession delegate
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
id<RCTURLRequestDelegate> delegate;
{
std::lock_guard<std::mutex> lock(_mutex);
delegate = [_delegates objectForKey:task];
}
[delegate URLRequest:task didSendDataWithProgress:totalBytesSent];
}
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest *))completionHandler
{
// Reset the cookies on redirect.
// This is necessary because we're not letting iOS handle cookies by itself
NSMutableURLRequest *nextRequest = [request mutableCopy];
NSArray<NSHTTPCookie *> *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:request.URL];
nextRequest.allHTTPHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
completionHandler(nextRequest);
}
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)task
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
id<RCTURLRequestDelegate> delegate;
{
std::lock_guard<std::mutex> lock(_mutex);
delegate = [_delegates objectForKey:task];
}
[delegate URLRequest:task didReceiveResponse:response];
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)task
didReceiveData:(NSData *)data
{
id<RCTURLRequestDelegate> delegate;
{
std::lock_guard<std::mutex> lock(_mutex);
delegate = [_delegates objectForKey:task];
}
[delegate URLRequest:task didReceiveData:data];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
id<RCTURLRequestDelegate> delegate;
{
std::lock_guard<std::mutex> lock(_mutex);
delegate = [_delegates objectForKey:task];
[_delegates removeObjectForKey:task];
}
[delegate URLRequest:task didCompleteWithError:error];
}
@end