diff --git a/src/ios/IONAssetHandler.h b/src/ios/IONAssetHandler.h index aee8d1c7..d0d897cb 100644 --- a/src/ios/IONAssetHandler.h +++ b/src/ios/IONAssetHandler.h @@ -5,6 +5,7 @@ @property (nonatomic, strong) NSString * basePath; @property (nonatomic, strong) NSString * scheme; +@property (nonatomic) Boolean isRunning; -(void)setAssetPath:(NSString *)assetPath; - (instancetype)initWithBasePath:(NSString *)basePath andScheme:(NSString *)scheme; diff --git a/src/ios/IONAssetHandler.m b/src/ios/IONAssetHandler.m index 64cf5ec3..701382ff 100644 --- a/src/ios/IONAssetHandler.m +++ b/src/ios/IONAssetHandler.m @@ -19,14 +19,72 @@ - (instancetype)initWithBasePath:(NSString *)basePath andScheme:(NSString *)sche - (void)webView:(WKWebView *)webView startURLSchemeTask:(id )urlSchemeTask { + self.isRunning = true; + Boolean loadFile = true; NSString * startPath = @""; NSURL * url = urlSchemeTask.request.URL; - NSString * stringToLoad = url.path; + NSDictionary * header = urlSchemeTask.request.allHTTPHeaderFields; + NSMutableString * stringToLoad = [NSMutableString string]; + [stringToLoad appendString:url.path]; NSString * scheme = url.scheme; + NSString * method = urlSchemeTask.request.HTTPMethod; + NSData * body = urlSchemeTask.request.HTTPBody; + NSData * data; + NSInteger statusCode; if ([scheme isEqualToString:self.scheme]) { if ([stringToLoad hasPrefix:@"/_app_file_"]) { startPath = [stringToLoad stringByReplacingOccurrencesOfString:@"/_app_file_" withString:@""]; + } else if ([stringToLoad hasPrefix:@"/_http_proxy_"]||[stringToLoad hasPrefix:@"/_https_proxy_"]) { + if(url.query) { + [stringToLoad appendString:@"?"]; + [stringToLoad appendString:url.query]; + } + loadFile = false; + startPath = [stringToLoad stringByReplacingOccurrencesOfString:@"/_http_proxy_" withString:@"http://"]; + startPath = [startPath stringByReplacingOccurrencesOfString:@"/_https_proxy_" withString:@"https://"]; + NSURL * requestUrl = [NSURL URLWithString:startPath]; + WKWebsiteDataStore* dataStore = [WKWebsiteDataStore defaultDataStore]; + WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore; + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + [request setHTTPMethod:method]; + [request setURL:requestUrl]; + if (body) { + [request setHTTPBody:body]; + } + [request setAllHTTPHeaderFields:header]; + [request setHTTPShouldHandleCookies:YES]; + + [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + if(error) { + NSLog(@"Proxy error: %@", error); + } + + // set cookies to WKWebView + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; + if(httpResponse) { + NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[httpResponse allHeaderFields] forURL:response.URL]; + [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:httpResponse.URL mainDocumentURL:nil]; + cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; + + for (NSHTTPCookie* c in cookies) + { + dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ + //running in background thread is necessary because setCookie otherwise fails + dispatch_async(dispatch_get_main_queue(), ^(void){ + [cookieStore setCookie:c completionHandler:nil]; + }); + }); + }; + } + + // Do not use urlSchemeTask if it has been closed in stopURLSchemeTask + if(self.isRunning) { + [urlSchemeTask didReceiveResponse:response]; + [urlSchemeTask didReceiveData:data]; + [urlSchemeTask didFinish]; + } + }] resume]; } else { startPath = self.basePath ? self.basePath : @""; if ([stringToLoad isEqualToString:@""] || [url.pathExtension isEqualToString:@""]) { @@ -36,36 +94,39 @@ - (void)webView:(WKWebView *)webView startURLSchemeTask:(id )ur } } } - NSError * fileError = nil; - NSData * data = nil; - if ([self isMediaExtension:url.pathExtension]) { - data = [NSData dataWithContentsOfFile:startPath options:NSDataReadingMappedIfSafe error:&fileError]; - } - if (!data || fileError) { - data = [[NSData alloc] initWithContentsOfFile:startPath]; - } - NSInteger statusCode = 200; - if (!data) { - statusCode = 404; - } - NSURL * localUrl = [NSURL URLWithString:url.absoluteString]; - NSString * mimeType = [self getMimeType:url.pathExtension]; - id response = nil; - if (data && [self isMediaExtension:url.pathExtension]) { - response = [[NSURLResponse alloc] initWithURL:localUrl MIMEType:mimeType expectedContentLength:data.length textEncodingName:nil]; - } else { - NSDictionary * headers = @{ @"Content-Type" : mimeType, @"Cache-Control": @"no-cache"}; - response = [[NSHTTPURLResponse alloc] initWithURL:localUrl statusCode:statusCode HTTPVersion:nil headerFields:headers]; - } - - [urlSchemeTask didReceiveResponse:response]; - [urlSchemeTask didReceiveData:data]; - [urlSchemeTask didFinish]; + if(loadFile) { + NSError * fileError = nil; + data = nil; + if ([self isMediaExtension:url.pathExtension]) { + data = [NSData dataWithContentsOfFile:startPath options:NSDataReadingMappedIfSafe error:&fileError]; + } + if (!data || fileError) { + data = [[NSData alloc] initWithContentsOfFile:startPath]; + } + statusCode = 200; + if (!data) { + statusCode = 404; + } + NSURL * localUrl = [NSURL URLWithString:url.absoluteString]; + NSString * mimeType = [self getMimeType:url.pathExtension]; + id response = nil; + if (data && [self isMediaExtension:url.pathExtension]) { + response = [[NSURLResponse alloc] initWithURL:localUrl MIMEType:mimeType expectedContentLength:data.length textEncodingName:nil]; + } else { + NSDictionary * headers = @{ @"Content-Type" : mimeType, @"Cache-Control": @"no-cache"}; + response = [[NSHTTPURLResponse alloc] initWithURL:localUrl statusCode:statusCode HTTPVersion:nil headerFields:headers]; + } + + [urlSchemeTask didReceiveResponse:response]; + [urlSchemeTask didReceiveData:data]; + [urlSchemeTask didFinish]; + } } - (void)webView:(nonnull WKWebView *)webView stopURLSchemeTask:(nonnull id)urlSchemeTask { + self.isRunning = false; NSLog(@"stop"); } diff --git a/src/www/util.js b/src/www/util.js index ba52a8e9..223695bc 100644 --- a/src/www/util.js +++ b/src/www/util.js @@ -2,6 +2,8 @@ var exec = require('cordova/exec'); var WebView = { convertFileSrc: function(url) { + const convertHttp = !location.protocol.startsWith("http") && !location.protocol.startsWith("https") + if (!url) { return url; } @@ -11,6 +13,12 @@ var WebView = { if (url.indexOf('file://')===0) { return window.WEBVIEW_SERVER_URL + url.replace('file://', '/_app_file_'); } + if (convertHttp && url.url.indexOf('http://')===0) { + return window.WEBVIEW_SERVER_URL + '/_http_proxy_' + encodeURIComponent(url.replace('http://', '')); + } + if (convertHttp && url.url.indexOf('https://')===0) { + return window.WEBVIEW_SERVER_URL + '/_https_proxy_' + encodeURIComponent(url.replace('https://', '')); + } if (url.indexOf('content://')===0) { return window.WEBVIEW_SERVER_URL + url.replace('content:/', '/_app_content_'); }