151 lines
4.4 KiB
Plaintext
151 lines
4.4 KiB
Plaintext
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import "RCTHTTPRequestHandler.h"
|
|
|
|
#import <mutex>
|
|
|
|
#import "RCTNetworking.h"
|
|
|
|
@interface RCTHTTPRequestHandler () <NSURLSessionDataDelegate>
|
|
|
|
@end
|
|
|
|
@implementation RCTHTTPRequestHandler
|
|
{
|
|
NSMapTable *_delegates;
|
|
NSURLSession *_session;
|
|
std::mutex _mutex;
|
|
}
|
|
|
|
@synthesize bridge = _bridge;
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
- (void)invalidate
|
|
{
|
|
[_session invalidateAndCancel];
|
|
_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]) {
|
|
NSOperationQueue *callbackQueue = [NSOperationQueue new];
|
|
callbackQueue.maxConcurrentOperationCount = 1;
|
|
callbackQueue.underlyingQueue = [[_bridge networking] methodQueue];
|
|
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
[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];
|
|
}
|
|
|
|
NSURLSessionDataTask *task = [_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
|
|
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
|